mirror of
https://github.com/SigNoz/signoz.git
synced 2026-07-23 14:30:37 +01:00
Compare commits
14 Commits
issue_5721
...
querier/te
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63e890a20e | ||
|
|
66c7e2d157 | ||
|
|
3c5c2cdcd9 | ||
|
|
cd1861ff87 | ||
|
|
f0a0b95ecd | ||
|
|
38340b5027 | ||
|
|
1783b942a2 | ||
|
|
ab3ed06fc0 | ||
|
|
fba56e9a64 | ||
|
|
b483cb3545 | ||
|
|
cbc8b5424b | ||
|
|
7ac6df6fb0 | ||
|
|
8c6a0de8c3 | ||
|
|
c7abe0fe7b |
@@ -2748,7 +2748,6 @@ components:
|
||||
links:
|
||||
items:
|
||||
$ref: '#/components/schemas/DashboardtypesLink'
|
||||
nullable: true
|
||||
type: array
|
||||
panels:
|
||||
additionalProperties:
|
||||
@@ -2765,6 +2764,7 @@ components:
|
||||
- variables
|
||||
- panels
|
||||
- layouts
|
||||
- links
|
||||
type: object
|
||||
DashboardtypesDashboardView:
|
||||
properties:
|
||||
@@ -2843,14 +2843,22 @@ components:
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
DashboardtypesDynamicVariableSignal:
|
||||
enum:
|
||||
- traces
|
||||
- logs
|
||||
- metrics
|
||||
- all
|
||||
type: string
|
||||
DashboardtypesDynamicVariableSpec:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
signal:
|
||||
$ref: '#/components/schemas/TelemetrytypesSignal'
|
||||
$ref: '#/components/schemas/DashboardtypesDynamicVariableSignal'
|
||||
required:
|
||||
- name
|
||||
- signal
|
||||
type: object
|
||||
DashboardtypesFillMode:
|
||||
enum:
|
||||
@@ -3393,7 +3401,6 @@ components:
|
||||
links:
|
||||
items:
|
||||
$ref: '#/components/schemas/DashboardtypesLink'
|
||||
nullable: true
|
||||
type: array
|
||||
plugin:
|
||||
$ref: '#/components/schemas/DashboardtypesPanelPlugin'
|
||||
@@ -3405,6 +3412,7 @@ components:
|
||||
- display
|
||||
- plugin
|
||||
- queries
|
||||
- links
|
||||
type: object
|
||||
DashboardtypesPatchOp:
|
||||
enum:
|
||||
@@ -4299,8 +4307,6 @@ components:
|
||||
type: object
|
||||
nodeCountsByReadiness:
|
||||
$ref: '#/components/schemas/InframonitoringtypesNodeCountsByReadiness'
|
||||
podCountsByPhase:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
|
||||
podCountsByStatus:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
|
||||
required:
|
||||
@@ -4310,7 +4316,6 @@ components:
|
||||
- clusterMemory
|
||||
- clusterMemoryAllocatable
|
||||
- nodeCountsByReadiness
|
||||
- podCountsByPhase
|
||||
- podCountsByStatus
|
||||
- counts
|
||||
- meta
|
||||
@@ -4520,8 +4525,6 @@ components:
|
||||
type: object
|
||||
misscheduledNodes:
|
||||
type: integer
|
||||
podCountsByPhase:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
|
||||
podCountsByStatus:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
|
||||
readyNodes:
|
||||
@@ -4538,7 +4541,6 @@ components:
|
||||
- currentNodes
|
||||
- readyNodes
|
||||
- misscheduledNodes
|
||||
- podCountsByPhase
|
||||
- podCountsByStatus
|
||||
- meta
|
||||
type: object
|
||||
@@ -4593,8 +4595,6 @@ components:
|
||||
type: string
|
||||
nullable: true
|
||||
type: object
|
||||
podCountsByPhase:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
|
||||
podCountsByStatus:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
|
||||
required:
|
||||
@@ -4607,7 +4607,6 @@ components:
|
||||
- deploymentMemoryLimit
|
||||
- desiredPods
|
||||
- availablePods
|
||||
- podCountsByPhase
|
||||
- podCountsByStatus
|
||||
- meta
|
||||
type: object
|
||||
@@ -4739,8 +4738,6 @@ components:
|
||||
type: string
|
||||
nullable: true
|
||||
type: object
|
||||
podCountsByPhase:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
|
||||
podCountsByStatus:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
|
||||
successfulPods:
|
||||
@@ -4757,7 +4754,6 @@ components:
|
||||
- activePods
|
||||
- failedPods
|
||||
- successfulPods
|
||||
- podCountsByPhase
|
||||
- podCountsByStatus
|
||||
- meta
|
||||
type: object
|
||||
@@ -4867,15 +4863,12 @@ components:
|
||||
type: number
|
||||
namespaceName:
|
||||
type: string
|
||||
podCountsByPhase:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
|
||||
podCountsByStatus:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
|
||||
required:
|
||||
- namespaceName
|
||||
- namespaceCPU
|
||||
- namespaceMemory
|
||||
- podCountsByPhase
|
||||
- podCountsByStatus
|
||||
- counts
|
||||
- meta
|
||||
@@ -4941,15 +4934,12 @@ components:
|
||||
type: number
|
||||
nodeName:
|
||||
type: string
|
||||
podCountsByPhase:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
|
||||
podCountsByStatus:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
|
||||
required:
|
||||
- nodeName
|
||||
- condition
|
||||
- nodeCountsByReadiness
|
||||
- podCountsByPhase
|
||||
- podCountsByStatus
|
||||
- nodeCPU
|
||||
- nodeCPUAllocatable
|
||||
@@ -4977,25 +4967,6 @@ components:
|
||||
- total
|
||||
- endTimeBeforeRetention
|
||||
type: object
|
||||
InframonitoringtypesPodCountsByPhase:
|
||||
properties:
|
||||
failed:
|
||||
type: integer
|
||||
pending:
|
||||
type: integer
|
||||
running:
|
||||
type: integer
|
||||
succeeded:
|
||||
type: integer
|
||||
unknown:
|
||||
type: integer
|
||||
required:
|
||||
- pending
|
||||
- running
|
||||
- succeeded
|
||||
- failed
|
||||
- unknown
|
||||
type: object
|
||||
InframonitoringtypesPodCountsByStatus:
|
||||
properties:
|
||||
completed:
|
||||
@@ -5054,15 +5025,6 @@ components:
|
||||
- shutdown
|
||||
- unexpectedAdmissionError
|
||||
type: object
|
||||
InframonitoringtypesPodPhase:
|
||||
enum:
|
||||
- pending
|
||||
- running
|
||||
- succeeded
|
||||
- failed
|
||||
- unknown
|
||||
- no_data
|
||||
type: string
|
||||
InframonitoringtypesPodRecord:
|
||||
properties:
|
||||
meta:
|
||||
@@ -5082,8 +5044,6 @@ components:
|
||||
podCPURequest:
|
||||
format: double
|
||||
type: number
|
||||
podCountsByPhase:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
|
||||
podCountsByStatus:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
|
||||
podMemory:
|
||||
@@ -5095,8 +5055,6 @@ components:
|
||||
podMemoryRequest:
|
||||
format: double
|
||||
type: number
|
||||
podPhase:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodPhase'
|
||||
podRestarts:
|
||||
format: int64
|
||||
type: integer
|
||||
@@ -5112,8 +5070,6 @@ components:
|
||||
- podMemory
|
||||
- podMemoryRequest
|
||||
- podMemoryLimit
|
||||
- podPhase
|
||||
- podCountsByPhase
|
||||
- podStatus
|
||||
- podCountsByStatus
|
||||
- podRestarts
|
||||
@@ -5464,8 +5420,6 @@ components:
|
||||
type: string
|
||||
nullable: true
|
||||
type: object
|
||||
podCountsByPhase:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
|
||||
podCountsByStatus:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
|
||||
statefulSetCPU:
|
||||
@@ -5498,7 +5452,6 @@ components:
|
||||
- statefulSetMemoryLimit
|
||||
- desiredPods
|
||||
- currentPods
|
||||
- podCountsByPhase
|
||||
- podCountsByStatus
|
||||
- meta
|
||||
type: object
|
||||
@@ -16152,17 +16105,19 @@ paths:
|
||||
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.'
|
||||
k8s.node.condition_ready value) and per-group podCountsByStatus ({ pending,
|
||||
running, failed, unknown, crashLoopBackOff, imagePullBackOff, errImagePull,
|
||||
createContainerConfigError, containerCreating, oomKilled, completed, error,
|
||||
containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError
|
||||
} reflecting each pod''s latest kubectl-style display status). 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.'
|
||||
operationId: ListClusters
|
||||
requestBody:
|
||||
content:
|
||||
@@ -16230,13 +16185,16 @@ paths:
|
||||
the number of nodes running at least one ready daemon pod) and misscheduledNodes
|
||||
(k8s.daemonset.misscheduled_nodes, the number of nodes running the daemon
|
||||
pod but not supposed to) — 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
|
||||
also reports per-group podCountsByStatus ({ pending, running, failed, unknown,
|
||||
crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError,
|
||||
containerCreating, oomKilled, completed, error, containerCannotRun, evicted,
|
||||
nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } reflecting each
|
||||
pod''s latest kubectl-style display status). 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 / ready_nodes / misscheduled_nodes,
|
||||
and pagination via offset/limit. Also reports whether the requested time range
|
||||
falls before the data retention boundary. Numeric metric fields (daemonSetCPU,
|
||||
@@ -16304,17 +16262,19 @@ paths:
|
||||
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,
|
||||
availablePods (k8s.deployment.available) replica counts and per-group podCountsByStatus
|
||||
({ pending, running, failed, unknown, crashLoopBackOff, imagePullBackOff,
|
||||
errImagePull, createContainerConfigError, containerCreating, oomKilled, completed,
|
||||
error, containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError
|
||||
} reflecting each pod''s latest kubectl-style display status). 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.'
|
||||
@@ -16449,9 +16409,12 @@ paths:
|
||||
(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).
|
||||
It also reports per-group podCountsByStatus ({ pending, running, failed, unknown,
|
||||
crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError,
|
||||
containerCreating, oomKilled, completed, error, containerCannotRun, evicted,
|
||||
nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } reflecting each
|
||||
pod''s latest kubectl-style display status); note podCountsByStatus.failed
|
||||
(current pod status) 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
|
||||
@@ -16601,16 +16564,18 @@ paths:
|
||||
deprecated: false
|
||||
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.'
|
||||
plus per-group podCountsByStatus ({ pending, running, failed, unknown, crashLoopBackOff,
|
||||
imagePullBackOff, errImagePull, createContainerConfigError, containerCreating,
|
||||
oomKilled, completed, error, containerCannotRun, evicted, nodeAffinity, nodeLost,
|
||||
shutdown, unexpectedAdmissionError } reflecting each pod''s latest kubectl-style
|
||||
display status 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.'
|
||||
operationId: ListNamespaces
|
||||
requestBody:
|
||||
content:
|
||||
@@ -16670,18 +16635,21 @@ paths:
|
||||
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.'
|
||||
in the window) and per-group podCountsByStatus ({ pending, running, failed,
|
||||
unknown, crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError,
|
||||
containerCreating, oomKilled, completed, error, containerCannotRun, evicted,
|
||||
nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } for pods scheduled
|
||||
on the listed nodes, reflecting each pod''s latest kubectl-style display status).
|
||||
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.'
|
||||
operationId: ListNodes
|
||||
requestBody:
|
||||
content:
|
||||
@@ -16740,20 +16708,23 @@ paths:
|
||||
deprecated: false
|
||||
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,
|
||||
utilization, current pod status (kubectl-style display status such as Running/Pending/CrashLoopBackOff,
|
||||
or 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.'
|
||||
is one pod with its current status) or ''grouped_list'' for custom groupBy
|
||||
keys (each row aggregates pods in the group with per-status counts under podCountsByStatus:
|
||||
{ pending, running, failed, unknown, crashLoopBackOff, imagePullBackOff, errImagePull,
|
||||
createContainerConfigError, containerCreating, oomKilled, completed, error,
|
||||
containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError
|
||||
} derived from each pod''s latest kubectl-style display status 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.'
|
||||
operationId: ListPods
|
||||
requestBody:
|
||||
content:
|
||||
@@ -16886,16 +16857,19 @@ paths:
|
||||
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,
|
||||
podCountsByStatus ({ pending, running, failed, unknown, crashLoopBackOff,
|
||||
imagePullBackOff, errImagePull, createContainerConfigError, containerCreating,
|
||||
oomKilled, completed, error, containerCannotRun, evicted, nodeAffinity, nodeLost,
|
||||
shutdown, unexpectedAdmissionError } reflecting each pod''s latest kubectl-style
|
||||
display status). 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.'
|
||||
operationId: ListStatefulSets
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
"antd": "5.11.0",
|
||||
"antd-table-saveas-excel": "2.2.1",
|
||||
"antlr4": "4.13.2",
|
||||
"axios": "1.16.0",
|
||||
"axios": "1.18.0",
|
||||
"babel-jest": "^29.6.4",
|
||||
"chart.js": "3.9.1",
|
||||
"chartjs-adapter-date-fns": "^2.0.0",
|
||||
@@ -74,7 +74,7 @@
|
||||
"crypto-js": "4.2.0",
|
||||
"d3-hierarchy": "3.1.2",
|
||||
"dayjs": "^1.10.7",
|
||||
"dompurify": "3.4.11",
|
||||
"dompurify": "3.4.12",
|
||||
"event-source-polyfill": "1.0.31",
|
||||
"eventemitter3": "5.0.1",
|
||||
"history": "4.10.1",
|
||||
@@ -199,9 +199,9 @@
|
||||
"react-resizable": "3.0.4",
|
||||
"redux-mock-store": "1.5.4",
|
||||
"sass": "1.97.3",
|
||||
"sharp": "0.34.5",
|
||||
"sharp": "0.35.0",
|
||||
"stylelint": "17.7.0",
|
||||
"svgo": "4.0.1",
|
||||
"svgo": "4.0.2",
|
||||
"ts-jest": "29.4.9",
|
||||
"typescript-plugin-css-modules": "5.2.0",
|
||||
"use-sync-external-store": "1.6.0",
|
||||
|
||||
445
frontend/pnpm-lock.yaml
generated
445
frontend/pnpm-lock.yaml
generated
@@ -112,8 +112,8 @@ importers:
|
||||
specifier: 4.13.2
|
||||
version: 4.13.2
|
||||
axios:
|
||||
specifier: 1.16.0
|
||||
version: 1.16.0
|
||||
specifier: 1.18.0
|
||||
version: 1.18.0
|
||||
babel-jest:
|
||||
specifier: ^29.6.4
|
||||
version: 29.6.4(@babel/core@7.29.7)
|
||||
@@ -142,8 +142,8 @@ importers:
|
||||
specifier: ^1.10.7
|
||||
version: 1.11.20
|
||||
dompurify:
|
||||
specifier: 3.4.11
|
||||
version: 3.4.11
|
||||
specifier: 3.4.12
|
||||
version: 3.4.12
|
||||
event-source-polyfill:
|
||||
specifier: 1.0.31
|
||||
version: 1.0.31
|
||||
@@ -476,14 +476,14 @@ importers:
|
||||
specifier: 1.97.3
|
||||
version: 1.97.3
|
||||
sharp:
|
||||
specifier: 0.34.5
|
||||
version: 0.34.5
|
||||
specifier: 0.35.0
|
||||
version: 0.35.0
|
||||
stylelint:
|
||||
specifier: 17.7.0
|
||||
version: 17.7.0(typescript@5.9.3)
|
||||
svgo:
|
||||
specifier: 4.0.1
|
||||
version: 4.0.1
|
||||
specifier: 4.0.2
|
||||
version: 4.0.2
|
||||
ts-jest:
|
||||
specifier: 29.4.9
|
||||
version: 29.4.9(@babel/core@7.29.7)(@jest/transform@30.4.1)(@jest/types@30.2.0)(babel-jest@29.6.4(@babel/core@7.29.7))(esbuild@0.28.1)(jest-util@30.4.1)(jest@30.2.0(@types/node@16.18.25)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@types/node@16.18.25)(typescript@5.9.3)))(typescript@5.9.3)
|
||||
@@ -501,7 +501,7 @@ importers:
|
||||
version: 0.5.1(rolldown-vite@7.3.1(@types/node@16.18.25)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.0)(sass@1.97.3)(stylus@0.62.0)(terser@5.46.2)(yaml@2.8.4))
|
||||
vite-plugin-image-optimizer:
|
||||
specifier: 2.0.3
|
||||
version: 2.0.3(rolldown-vite@7.3.1(@types/node@16.18.25)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.0)(sass@1.97.3)(stylus@0.62.0)(terser@5.46.2)(yaml@2.8.4))(sharp@0.34.5)(svgo@4.0.1)
|
||||
version: 2.0.3(rolldown-vite@7.3.1(@types/node@16.18.25)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.0)(sass@1.97.3)(stylus@0.62.0)(terser@5.46.2)(yaml@2.8.4))(sharp@0.35.0)(svgo@4.0.2)
|
||||
vite-tsconfig-paths:
|
||||
specifier: 6.1.1
|
||||
version: 6.1.1(rolldown-vite@7.3.1(@types/node@16.18.25)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.0)(sass@1.97.3)(stylus@0.62.0)(terser@5.46.2)(yaml@2.8.4))(typescript@5.9.3)
|
||||
@@ -1460,6 +1460,9 @@ packages:
|
||||
'@emnapi/core@1.8.1':
|
||||
resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==}
|
||||
|
||||
'@emnapi/runtime@1.11.2':
|
||||
resolution: {integrity: sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==}
|
||||
|
||||
'@emnapi/runtime@1.8.1':
|
||||
resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==}
|
||||
|
||||
@@ -1714,156 +1717,165 @@ packages:
|
||||
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
|
||||
engines: {node: '>=18.18'}
|
||||
|
||||
'@img/colour@1.0.0':
|
||||
resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==}
|
||||
'@img/colour@1.1.0':
|
||||
resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@img/sharp-darwin-arm64@0.34.5':
|
||||
resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
'@img/sharp-darwin-arm64@0.35.0':
|
||||
resolution: {integrity: sha512-ZgaYEwaj+lx/5n4W8GmZ2IYz0PQHjN5eqRcfijWGB+2Aq7ZInZGa0qJyAn6DEtyLuWHRSrmWOqT9q3qqTBvmUQ==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@img/sharp-darwin-x64@0.34.5':
|
||||
resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
'@img/sharp-darwin-x64@0.35.0':
|
||||
resolution: {integrity: sha512-c1z9LFpKB0slQW3RchwBE8iSVzGp70TNjUUO9k4BZwwW4HH7JBGHeIy4b+kk4n/kcBASb9evKCE3/7Slmslgiw==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@img/sharp-libvips-darwin-arm64@1.2.4':
|
||||
resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==}
|
||||
'@img/sharp-freebsd-wasm32@0.35.0':
|
||||
resolution: {integrity: sha512-Li2KTev0H90kEtnJHkI9xQojXt1AqWmFBMXiPw5kqd1jQgP7gi5HVK/qC5Rmh/59NuAwUuPzzPITmX22NomYYQ==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
os: [freebsd]
|
||||
|
||||
'@img/sharp-libvips-darwin-arm64@1.3.0':
|
||||
resolution: {integrity: sha512-EKbmBKtyTH+GPFDRw2TgK2oV6hyxxlJVIar4hoTYSNmIwipgMFdxPQqR392GmfdsPGWga0mCFN1cCKjRb9cljw==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@img/sharp-libvips-darwin-x64@1.2.4':
|
||||
resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==}
|
||||
'@img/sharp-libvips-darwin-x64@1.3.0':
|
||||
resolution: {integrity: sha512-Pl2OmOvrJ42adUllESxBsG54PfXLo1OYg9i3c5/5Ln/qJ0gZuTM9YMhQJPIbXqwidLRc/c2zuHt4RsrymmNv7A==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@img/sharp-libvips-linux-arm64@1.2.4':
|
||||
resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==}
|
||||
'@img/sharp-libvips-linux-arm64@1.3.0':
|
||||
resolution: {integrity: sha512-C0SqjoFKnszqa44EQ7xoaT48nnO0lOyXEULfXMWi8krrjOPGYkeK30Okzla6ATbBYsyZ0ySinK0FVkpv3DwzfQ==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-arm@1.2.4':
|
||||
resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==}
|
||||
'@img/sharp-libvips-linux-arm@1.3.0':
|
||||
resolution: {integrity: sha512-A8UpHoUDW4DwnXoV6+q3C1s7QLRAHtPDEjWuNZjwHMyoCNZnm0GeNN8ls9f/bsEYTRQRW96C/n34XJQHJ2fT7A==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-ppc64@1.2.4':
|
||||
resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==}
|
||||
'@img/sharp-libvips-linux-ppc64@1.3.0':
|
||||
resolution: {integrity: sha512-WOpkVxAjFd369iaIzEgNRreFD+gWdUMIGD5zplhNKNeqS6mm5dac3q2AFyCBmzYoAdouzZvRBgxy4z8QHZb4/A==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-riscv64@1.2.4':
|
||||
resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==}
|
||||
'@img/sharp-libvips-linux-riscv64@1.3.0':
|
||||
resolution: {integrity: sha512-DRWw0mOHusrCCuw2rqP87oLg6PGlkomVDFqw2hIwsSfwWpu4k3XLcBPaKKl6ct/GtL/cwNkgwjV/tc0Mqht3VA==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-s390x@1.2.4':
|
||||
resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==}
|
||||
'@img/sharp-libvips-linux-s390x@1.3.0':
|
||||
resolution: {integrity: sha512-9APy+nFWhHS+kzLgWZfLcyrUd7YqnAQVa4BPOo4xkoHpdoktOAPG4cEr9+Jpl0TtqfVmcMJimNL5qNTyyOHZNA==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-x64@1.2.4':
|
||||
resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==}
|
||||
'@img/sharp-libvips-linux-x64@1.3.0':
|
||||
resolution: {integrity: sha512-y9RNUYDe2A1UAdhLyfeOodGRszQdaEoe4nfOpp/sNVPl2CWIcUyFaDoCh4vPLPxu19803j2naLqZup2WxDXCLA==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-arm64@1.2.4':
|
||||
resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==}
|
||||
'@img/sharp-libvips-linuxmusl-arm64@1.3.0':
|
||||
resolution: {integrity: sha512-cC1wkC0Mlucd0KSiGrLkJnB/ZqPvZCntc/Lk7ZnYO5ZSbF2euNek4Xvxafojq+wN1q/W0eprdpUIjUr/EV2PBg==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-x64@1.2.4':
|
||||
resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==}
|
||||
'@img/sharp-libvips-linuxmusl-x64@1.3.0':
|
||||
resolution: {integrity: sha512-LiYMhUZicB1QG//+RvmYZpXJO8fYRENfp+MZUCnG9aw+AKvGAy9gPaCnuwsPcBFs8EV66M0NNxj9VHcNklE8zw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-linux-arm64@0.34.5':
|
||||
resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
'@img/sharp-linux-arm64@0.35.0':
|
||||
resolution: {integrity: sha512-4+4XHLNT5wDT0roYlHTEmH9lDKt0acf9Tv+3hM3iceOirkxrR404/3WjAYZ9F9CkHrxeRcGLJXbi4vluMZ9O+A==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-arm@0.34.5':
|
||||
resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
'@img/sharp-linux-arm@0.35.0':
|
||||
resolution: {integrity: sha512-VVlpEWwizEFIOom0zdoeKuO5nuTswzVE5uHcBNvHzmeHUpNFajY3HFfbQ+zIH4E2kVaZ/yVxmsShW56TtEy4uA==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-ppc64@0.34.5':
|
||||
resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
'@img/sharp-linux-ppc64@0.35.0':
|
||||
resolution: {integrity: sha512-N3hzbEpUTJC8pWpPVJvgzGxM+so/MAXc8O2s/53B0LL9ZGpfXpME7Wizkc5d/8fRBlBtkDjzoZGDCqqNDHqLEw==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-riscv64@0.34.5':
|
||||
resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
'@img/sharp-linux-riscv64@0.35.0':
|
||||
resolution: {integrity: sha512-l6vmKVPnbS0RhVMbyxP5meAARsbhCnBN4fy31qz0+3a6Rv4jEqfzDrT89y6ZPkCi0AJGnwp2En528yXo401Hpw==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-s390x@0.34.5':
|
||||
resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
'@img/sharp-linux-s390x@0.35.0':
|
||||
resolution: {integrity: sha512-MYlMiPFiv/EKPAHnp3yNZ9AAWFsxga9c5Bkc6wkar6bqzHLlkGVJHRm0u1ei+VXnZxp3Mz9MG9ZIsI8vSOf3sQ==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-x64@0.34.5':
|
||||
resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
'@img/sharp-linux-x64@0.35.0':
|
||||
resolution: {integrity: sha512-TYaItB5oj1ioXjhyn2xrR208vf+YuIIcHptQWRRaBmFhvIvL9D72DXN8w75xup0KXA8UdEAhQ9Qb2S49FD/9Cw==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linuxmusl-arm64@0.34.5':
|
||||
resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
'@img/sharp-linuxmusl-arm64@0.35.0':
|
||||
resolution: {integrity: sha512-DSTb6ijQzqe6DdAaOBVqJ/SYf1vO8EW5bK6X6LRXufEBebf2722VCdvBUtZ3rtV0x2ApfPNDy/p7LrrjaWjiyQ==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-linuxmusl-x64@0.34.5':
|
||||
resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
'@img/sharp-linuxmusl-x64@0.35.0':
|
||||
resolution: {integrity: sha512-K7ykQ+26Rt6+4BTU80AuGgTPIYX86UxiAKT4rcXX/WNTo7k1ZxpKz+TguHnwVpCqQK3B5PK0vZ0ZBe6nz/ib1w==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-wasm32@0.34.5':
|
||||
resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
'@img/sharp-wasm32@0.35.0':
|
||||
resolution: {integrity: sha512-9woLIFORERCr+6cWu87dQ22J34EExkhc73U1kZW0c+RclQqWetoodByp4dWZ/hN8/KVmTRAx2HOnUwib8AwZdA==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
|
||||
'@img/sharp-webcontainers-wasm32@0.35.0':
|
||||
resolution: {integrity: sha512-t+kie1TOyaDM6Dho+f+y0VqIUNhYQaKCUahuZVi0E0frgdiaOaPsDxDW3wfKacUdaNBCnK/ZDBMg33ydvHj8uA==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
cpu: [wasm32]
|
||||
|
||||
'@img/sharp-win32-arm64@0.34.5':
|
||||
resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
'@img/sharp-win32-arm64@0.35.0':
|
||||
resolution: {integrity: sha512-M5eKxug0dabbaWgFKvPa3odNs2OpaP+81NASfGKkt4GcYXpNhSu7CaeYxWkLNV6vHmUp4hnCxnxrUyhUJhXbKA==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@img/sharp-win32-ia32@0.34.5':
|
||||
resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
'@img/sharp-win32-ia32@0.35.0':
|
||||
resolution: {integrity: sha512-z0+pZ03QCDvdVN0Ez9IX/yjWC19ikMlXrmdYMwYNLTh2BLPx3hXWPvyqWfquZ0BTO9O6GVOjIVoTcyyacMnWlQ==}
|
||||
engines: {node: ^20.9.0}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@img/sharp-win32-x64@0.34.5':
|
||||
resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
'@img/sharp-win32-x64@0.35.0':
|
||||
resolution: {integrity: sha512-feNnlz5ZHKr0MY1LPHvZQyJeBkbo4ctsn0D8FvA53VTw5TC63rfEL2UrWbkSBR19htSE7Mw78xYVwdJqoMWVHw==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
@@ -4075,8 +4087,8 @@ packages:
|
||||
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
axios@1.16.0:
|
||||
resolution: {integrity: sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==}
|
||||
axios@1.18.0:
|
||||
resolution: {integrity: sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==}
|
||||
|
||||
babel-jest@29.6.4:
|
||||
resolution: {integrity: sha512-meLj23UlSLddj6PC+YTOFRgDAtjnZom8w/ACsrx0gtPtv5cJZk0A5Unk5bV4wixD7XaPCN1fQvpww8czkZURmw==}
|
||||
@@ -4881,8 +4893,8 @@ packages:
|
||||
resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
|
||||
engines: {node: '>= 4'}
|
||||
|
||||
dompurify@3.4.11:
|
||||
resolution: {integrity: sha512-zhlUV12GsaRzMsf9q5M254YhA4+VuF0fG+QFqu6aYpoGlKtz+w8//jBcGVYBgQkR5GHjUomejY84AV+/uPbWdw==}
|
||||
dompurify@3.4.12:
|
||||
resolution: {integrity: sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg==}
|
||||
|
||||
domutils@2.8.0:
|
||||
resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==}
|
||||
@@ -5448,10 +5460,6 @@ packages:
|
||||
resolution: {integrity: sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
hasown@2.0.2:
|
||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
hasown@2.0.4:
|
||||
resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -8062,10 +8070,6 @@ packages:
|
||||
sax@1.3.0:
|
||||
resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==}
|
||||
|
||||
sax@1.4.4:
|
||||
resolution: {integrity: sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==}
|
||||
engines: {node: '>=11.0.0'}
|
||||
|
||||
sax@1.6.0:
|
||||
resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==}
|
||||
engines: {node: '>=11.0.0'}
|
||||
@@ -8122,9 +8126,9 @@ packages:
|
||||
shallowequal@1.1.0:
|
||||
resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==}
|
||||
|
||||
sharp@0.34.5:
|
||||
resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
sharp@0.35.0:
|
||||
resolution: {integrity: sha512-BqvG5XbwPZ4NV0DK90d86leEECMsoa8bO0nqnKWlBDYxri4GJ7c4EDInaF6q20lTh/mATmnDIKWJFfXnoVfH5g==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
|
||||
shebang-command@2.0.0:
|
||||
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
|
||||
@@ -8376,8 +8380,8 @@ packages:
|
||||
svg-tags@1.0.0:
|
||||
resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==}
|
||||
|
||||
svgo@4.0.1:
|
||||
resolution: {integrity: sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==}
|
||||
svgo@4.0.2:
|
||||
resolution: {integrity: sha512-ekx94z1rRc5LDi6oSUaeRnYhd0UOJxdtQCL2rF8xpWxD3TPAsISWOrxezqGovqS38GRZOdpDfvQe3ts6F7nsng==}
|
||||
engines: {node: '>=16'}
|
||||
hasBin: true
|
||||
|
||||
@@ -10281,6 +10285,11 @@ snapshots:
|
||||
tslib: 2.8.1
|
||||
optional: true
|
||||
|
||||
'@emnapi/runtime@1.11.2':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
optional: true
|
||||
|
||||
'@emnapi/runtime@1.8.1':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
@@ -10444,7 +10453,7 @@ snapshots:
|
||||
'@types/string-hash': 1.1.3
|
||||
d3-interpolate: 3.0.1
|
||||
date-fns: 4.1.0
|
||||
dompurify: 3.4.11
|
||||
dompurify: 3.4.12
|
||||
eventemitter3: 5.0.1
|
||||
fast_array_intersect: 1.1.0
|
||||
history: 4.10.1
|
||||
@@ -10485,100 +10494,110 @@ snapshots:
|
||||
|
||||
'@humanwhocodes/retry@0.4.3': {}
|
||||
|
||||
'@img/colour@1.0.0': {}
|
||||
'@img/colour@1.1.0': {}
|
||||
|
||||
'@img/sharp-darwin-arm64@0.34.5':
|
||||
'@img/sharp-darwin-arm64@0.35.0':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-darwin-arm64': 1.2.4
|
||||
'@img/sharp-libvips-darwin-arm64': 1.3.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-darwin-x64@0.34.5':
|
||||
'@img/sharp-darwin-x64@0.35.0':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-darwin-x64': 1.2.4
|
||||
'@img/sharp-libvips-darwin-x64': 1.3.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-darwin-arm64@1.2.4':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-darwin-x64@1.2.4':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linux-arm64@1.2.4':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linux-arm@1.2.4':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linux-ppc64@1.2.4':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linux-riscv64@1.2.4':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linux-s390x@1.2.4':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linux-x64@1.2.4':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-arm64@1.2.4':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-x64@1.2.4':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linux-arm64@0.34.5':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linux-arm64': 1.2.4
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linux-arm@0.34.5':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linux-arm': 1.2.4
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linux-ppc64@0.34.5':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linux-ppc64': 1.2.4
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linux-riscv64@0.34.5':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linux-riscv64': 1.2.4
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linux-s390x@0.34.5':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linux-s390x': 1.2.4
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linux-x64@0.34.5':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linux-x64': 1.2.4
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linuxmusl-arm64@0.34.5':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linuxmusl-arm64': 1.2.4
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linuxmusl-x64@0.34.5':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linuxmusl-x64': 1.2.4
|
||||
optional: true
|
||||
|
||||
'@img/sharp-wasm32@0.34.5':
|
||||
'@img/sharp-freebsd-wasm32@0.35.0':
|
||||
dependencies:
|
||||
'@emnapi/runtime': 1.8.1
|
||||
'@img/sharp-wasm32': 0.35.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-win32-arm64@0.34.5':
|
||||
'@img/sharp-libvips-darwin-arm64@1.3.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-win32-ia32@0.34.5':
|
||||
'@img/sharp-libvips-darwin-x64@1.3.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-win32-x64@0.34.5':
|
||||
'@img/sharp-libvips-linux-arm64@1.3.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linux-arm@1.3.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linux-ppc64@1.3.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linux-riscv64@1.3.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linux-s390x@1.3.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linux-x64@1.3.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-arm64@1.3.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-x64@1.3.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linux-arm64@0.35.0':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linux-arm64': 1.3.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linux-arm@0.35.0':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linux-arm': 1.3.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linux-ppc64@0.35.0':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linux-ppc64': 1.3.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linux-riscv64@0.35.0':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linux-riscv64': 1.3.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linux-s390x@0.35.0':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linux-s390x': 1.3.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linux-x64@0.35.0':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linux-x64': 1.3.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linuxmusl-arm64@0.35.0':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linuxmusl-arm64': 1.3.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-linuxmusl-x64@0.35.0':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-linuxmusl-x64': 1.3.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-wasm32@0.35.0':
|
||||
dependencies:
|
||||
'@emnapi/runtime': 1.11.2
|
||||
optional: true
|
||||
|
||||
'@img/sharp-webcontainers-wasm32@0.35.0':
|
||||
dependencies:
|
||||
'@img/sharp-wasm32': 0.35.0
|
||||
optional: true
|
||||
|
||||
'@img/sharp-win32-arm64@0.35.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-win32-ia32@0.35.0':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-win32-x64@0.35.0':
|
||||
optional: true
|
||||
|
||||
'@isaacs/cliui@8.0.2':
|
||||
@@ -12983,13 +13002,15 @@ snapshots:
|
||||
dependencies:
|
||||
possible-typed-array-names: 1.1.0
|
||||
|
||||
axios@1.16.0:
|
||||
axios@1.18.0:
|
||||
dependencies:
|
||||
follow-redirects: 1.16.0
|
||||
form-data: 4.0.6
|
||||
https-proxy-agent: 5.0.1
|
||||
proxy-from-env: 2.1.0
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
- supports-color
|
||||
|
||||
babel-jest@29.6.4(@babel/core@7.29.7):
|
||||
dependencies:
|
||||
@@ -13843,7 +13864,7 @@ snapshots:
|
||||
dependencies:
|
||||
domelementtype: 2.3.0
|
||||
|
||||
dompurify@3.4.11:
|
||||
dompurify@3.4.12:
|
||||
optionalDependencies:
|
||||
'@types/trusted-types': 2.0.7
|
||||
|
||||
@@ -14498,10 +14519,6 @@ snapshots:
|
||||
dependencies:
|
||||
hookified: 1.15.1
|
||||
|
||||
hasown@2.0.2:
|
||||
dependencies:
|
||||
function-bind: 1.1.2
|
||||
|
||||
hasown@2.0.4:
|
||||
dependencies:
|
||||
function-bind: 1.1.2
|
||||
@@ -14738,7 +14755,7 @@ snapshots:
|
||||
internal-slot@1.1.0:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
hasown: 2.0.2
|
||||
hasown: 2.0.4
|
||||
side-channel: 1.1.0
|
||||
|
||||
internmap@2.0.3: {}
|
||||
@@ -14792,7 +14809,7 @@ snapshots:
|
||||
|
||||
is-core-module@2.16.1:
|
||||
dependencies:
|
||||
hasown: 2.0.2
|
||||
hasown: 2.0.4
|
||||
|
||||
is-date-object@1.1.0:
|
||||
dependencies:
|
||||
@@ -14861,7 +14878,7 @@ snapshots:
|
||||
call-bound: 1.0.4
|
||||
gopd: 1.2.0
|
||||
has-tostringtag: 1.0.2
|
||||
hasown: 2.0.2
|
||||
hasown: 2.0.4
|
||||
|
||||
is-set@2.0.3: {}
|
||||
|
||||
@@ -16177,7 +16194,7 @@ snapshots:
|
||||
|
||||
monaco-editor@0.55.1:
|
||||
dependencies:
|
||||
dompurify: 3.4.11
|
||||
dompurify: 3.4.12
|
||||
marked: 14.0.0
|
||||
|
||||
motion-dom@11.18.1:
|
||||
@@ -16272,7 +16289,7 @@ snapshots:
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
iconv-lite: 0.6.3
|
||||
sax: 1.4.4
|
||||
sax: 1.6.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
optional: true
|
||||
@@ -17741,9 +17758,6 @@ snapshots:
|
||||
sax@1.3.0:
|
||||
optional: true
|
||||
|
||||
sax@1.4.4:
|
||||
optional: true
|
||||
|
||||
sax@1.6.0: {}
|
||||
|
||||
saxes@6.0.0:
|
||||
@@ -17797,36 +17811,37 @@ snapshots:
|
||||
|
||||
shallowequal@1.1.0: {}
|
||||
|
||||
sharp@0.34.5:
|
||||
sharp@0.35.0:
|
||||
dependencies:
|
||||
'@img/colour': 1.0.0
|
||||
'@img/colour': 1.1.0
|
||||
detect-libc: 2.1.2
|
||||
semver: 7.8.5
|
||||
optionalDependencies:
|
||||
'@img/sharp-darwin-arm64': 0.34.5
|
||||
'@img/sharp-darwin-x64': 0.34.5
|
||||
'@img/sharp-libvips-darwin-arm64': 1.2.4
|
||||
'@img/sharp-libvips-darwin-x64': 1.2.4
|
||||
'@img/sharp-libvips-linux-arm': 1.2.4
|
||||
'@img/sharp-libvips-linux-arm64': 1.2.4
|
||||
'@img/sharp-libvips-linux-ppc64': 1.2.4
|
||||
'@img/sharp-libvips-linux-riscv64': 1.2.4
|
||||
'@img/sharp-libvips-linux-s390x': 1.2.4
|
||||
'@img/sharp-libvips-linux-x64': 1.2.4
|
||||
'@img/sharp-libvips-linuxmusl-arm64': 1.2.4
|
||||
'@img/sharp-libvips-linuxmusl-x64': 1.2.4
|
||||
'@img/sharp-linux-arm': 0.34.5
|
||||
'@img/sharp-linux-arm64': 0.34.5
|
||||
'@img/sharp-linux-ppc64': 0.34.5
|
||||
'@img/sharp-linux-riscv64': 0.34.5
|
||||
'@img/sharp-linux-s390x': 0.34.5
|
||||
'@img/sharp-linux-x64': 0.34.5
|
||||
'@img/sharp-linuxmusl-arm64': 0.34.5
|
||||
'@img/sharp-linuxmusl-x64': 0.34.5
|
||||
'@img/sharp-wasm32': 0.34.5
|
||||
'@img/sharp-win32-arm64': 0.34.5
|
||||
'@img/sharp-win32-ia32': 0.34.5
|
||||
'@img/sharp-win32-x64': 0.34.5
|
||||
'@img/sharp-darwin-arm64': 0.35.0
|
||||
'@img/sharp-darwin-x64': 0.35.0
|
||||
'@img/sharp-freebsd-wasm32': 0.35.0
|
||||
'@img/sharp-libvips-darwin-arm64': 1.3.0
|
||||
'@img/sharp-libvips-darwin-x64': 1.3.0
|
||||
'@img/sharp-libvips-linux-arm': 1.3.0
|
||||
'@img/sharp-libvips-linux-arm64': 1.3.0
|
||||
'@img/sharp-libvips-linux-ppc64': 1.3.0
|
||||
'@img/sharp-libvips-linux-riscv64': 1.3.0
|
||||
'@img/sharp-libvips-linux-s390x': 1.3.0
|
||||
'@img/sharp-libvips-linux-x64': 1.3.0
|
||||
'@img/sharp-libvips-linuxmusl-arm64': 1.3.0
|
||||
'@img/sharp-libvips-linuxmusl-x64': 1.3.0
|
||||
'@img/sharp-linux-arm': 0.35.0
|
||||
'@img/sharp-linux-arm64': 0.35.0
|
||||
'@img/sharp-linux-ppc64': 0.35.0
|
||||
'@img/sharp-linux-riscv64': 0.35.0
|
||||
'@img/sharp-linux-s390x': 0.35.0
|
||||
'@img/sharp-linux-x64': 0.35.0
|
||||
'@img/sharp-linuxmusl-arm64': 0.35.0
|
||||
'@img/sharp-linuxmusl-x64': 0.35.0
|
||||
'@img/sharp-webcontainers-wasm32': 0.35.0
|
||||
'@img/sharp-win32-arm64': 0.35.0
|
||||
'@img/sharp-win32-ia32': 0.35.0
|
||||
'@img/sharp-win32-x64': 0.35.0
|
||||
|
||||
shebang-command@2.0.0:
|
||||
dependencies:
|
||||
@@ -18124,7 +18139,7 @@ snapshots:
|
||||
|
||||
svg-tags@1.0.0: {}
|
||||
|
||||
svgo@4.0.1:
|
||||
svgo@4.0.2:
|
||||
dependencies:
|
||||
commander: 11.1.0
|
||||
css-select: 5.2.2
|
||||
@@ -18591,14 +18606,14 @@ snapshots:
|
||||
pathe: 0.2.0
|
||||
vite: rolldown-vite@7.3.1(@types/node@16.18.25)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.0)(sass@1.97.3)(stylus@0.62.0)(terser@5.46.2)(yaml@2.8.4)
|
||||
|
||||
vite-plugin-image-optimizer@2.0.3(rolldown-vite@7.3.1(@types/node@16.18.25)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.0)(sass@1.97.3)(stylus@0.62.0)(terser@5.46.2)(yaml@2.8.4))(sharp@0.34.5)(svgo@4.0.1):
|
||||
vite-plugin-image-optimizer@2.0.3(rolldown-vite@7.3.1(@types/node@16.18.25)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.0)(sass@1.97.3)(stylus@0.62.0)(terser@5.46.2)(yaml@2.8.4))(sharp@0.35.0)(svgo@4.0.2):
|
||||
dependencies:
|
||||
ansi-colors: 4.1.3
|
||||
pathe: 2.0.3
|
||||
vite: rolldown-vite@7.3.1(@types/node@16.18.25)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.0)(sass@1.97.3)(stylus@0.62.0)(terser@5.46.2)(yaml@2.8.4)
|
||||
optionalDependencies:
|
||||
sharp: 0.34.5
|
||||
svgo: 4.0.1
|
||||
sharp: 0.35.0
|
||||
svgo: 4.0.2
|
||||
|
||||
vite-tsconfig-paths@6.1.1(rolldown-vite@7.3.1(@types/node@16.18.25)(esbuild@0.28.1)(jiti@2.6.1)(less@4.4.0)(sass@1.97.3)(stylus@0.62.0)(terser@5.46.2)(yaml@2.8.4))(typescript@5.9.3):
|
||||
dependencies:
|
||||
|
||||
@@ -136,7 +136,7 @@ export const invalidateGetChecks = async (
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 podCountsByStatus ({ pending, running, failed, unknown, crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError, containerCreating, oomKilled, completed, error, containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } reflecting each pod's latest kubectl-style display status). 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.
|
||||
* @summary List Clusters for Infra Monitoring
|
||||
*/
|
||||
export const listClusters = (
|
||||
@@ -219,7 +219,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), currentNodes (k8s.daemonset.current_scheduled_nodes, the number of nodes the daemonset currently runs on), readyNodes (k8s.daemonset.ready_nodes, the number of nodes running at least one ready daemon pod) and misscheduledNodes (k8s.daemonset.misscheduled_nodes, the number of nodes running the daemon pod but not supposed to) — 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 / ready_nodes / misscheduled_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, readyNodes, misscheduledNodes) 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), currentNodes (k8s.daemonset.current_scheduled_nodes, the number of nodes the daemonset currently runs on), readyNodes (k8s.daemonset.ready_nodes, the number of nodes running at least one ready daemon pod) and misscheduledNodes (k8s.daemonset.misscheduled_nodes, the number of nodes running the daemon pod but not supposed to) — note these are node counts, not pod counts. It also reports per-group podCountsByStatus ({ pending, running, failed, unknown, crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError, containerCreating, oomKilled, completed, error, containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } reflecting each pod's latest kubectl-style display status). 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 / ready_nodes / misscheduled_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, readyNodes, misscheduledNodes) return -1 as a sentinel when no data is available for that field.
|
||||
* @summary List DaemonSets for Infra Monitoring
|
||||
*/
|
||||
export const listDaemonSets = (
|
||||
@@ -302,7 +302,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 podCountsByStatus ({ pending, running, failed, unknown, crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError, containerCreating, oomKilled, completed, error, containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } reflecting each pod's latest kubectl-style display status). 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.
|
||||
* @summary List Deployments for Infra Monitoring
|
||||
*/
|
||||
export const listDeployments = (
|
||||
@@ -468,7 +468,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 podCountsByStatus ({ pending, running, failed, unknown, crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError, containerCreating, oomKilled, completed, error, containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } reflecting each pod's latest kubectl-style display status); note podCountsByStatus.failed (current pod status) 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.
|
||||
* @summary List Jobs for Infra Monitoring
|
||||
*/
|
||||
export const listJobs = (
|
||||
@@ -634,7 +634,7 @@ export const useListContainers = <
|
||||
return useMutation(getListContainersMutationOptions(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 podCountsByStatus ({ pending, running, failed, unknown, crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError, containerCreating, oomKilled, completed, error, containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } reflecting each pod's latest kubectl-style display status 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.
|
||||
* @summary List Namespaces for Infra Monitoring
|
||||
*/
|
||||
export const listNamespaces = (
|
||||
@@ -717,7 +717,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 podCountsByStatus ({ pending, running, failed, unknown, crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError, containerCreating, oomKilled, completed, error, containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } for pods scheduled on the listed nodes, reflecting each pod's latest kubectl-style display status). 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.
|
||||
* @summary List Nodes for Infra Monitoring
|
||||
*/
|
||||
export const listNodes = (
|
||||
@@ -800,7 +800,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 status (kubectl-style display status such as Running/Pending/CrashLoopBackOff, or 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 status) or 'grouped_list' for custom groupBy keys (each row aggregates pods in the group with per-status counts under podCountsByStatus: { pending, running, failed, unknown, crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError, containerCreating, oomKilled, completed, error, containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } derived from each pod's latest kubectl-style display status 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.
|
||||
* @summary List Pods for Infra Monitoring
|
||||
*/
|
||||
export const listPods = (
|
||||
@@ -966,7 +966,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 podCountsByStatus ({ pending, running, failed, unknown, crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError, containerCreating, oomKilled, completed, error, containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } reflecting each pod's latest kubectl-style display status). 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.
|
||||
* @summary List StatefulSets for Infra Monitoring
|
||||
*/
|
||||
export const listStatefulSets = (
|
||||
|
||||
@@ -4626,9 +4626,9 @@ export interface DashboardtypesQueryDTO {
|
||||
export interface DashboardtypesPanelSpecDTO {
|
||||
display: DashboardtypesDisplayDTO;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
links?: DashboardtypesLinkDTO[] | null;
|
||||
links: DashboardtypesLinkDTO[];
|
||||
plugin: DashboardtypesPanelPluginDTO;
|
||||
/**
|
||||
* @type array
|
||||
@@ -4668,12 +4668,18 @@ export type DashboardtypesVariableDefaultValueDTO = string | string[];
|
||||
export enum DashboardtypesVariablePluginVariantGithubComSigNozSignozPkgTypesDashboardtypesDynamicVariableSpecDTOKind {
|
||||
'signoz/DynamicVariable' = 'signoz/DynamicVariable',
|
||||
}
|
||||
export enum DashboardtypesDynamicVariableSignalDTO {
|
||||
traces = 'traces',
|
||||
logs = 'logs',
|
||||
metrics = 'metrics',
|
||||
all = 'all',
|
||||
}
|
||||
export interface DashboardtypesDynamicVariableSpecDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name: string;
|
||||
signal?: TelemetrytypesSignalDTO;
|
||||
signal: DashboardtypesDynamicVariableSignalDTO;
|
||||
}
|
||||
|
||||
export interface DashboardtypesVariablePluginVariantGithubComSigNozSignozPkgTypesDashboardtypesDynamicVariableSpecDTO {
|
||||
@@ -4815,9 +4821,9 @@ export interface DashboardtypesDashboardSpecDTO {
|
||||
*/
|
||||
layouts: DashboardtypesLayoutDTO[];
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
links?: DashboardtypesLinkDTO[] | null;
|
||||
links: DashboardtypesLinkDTO[];
|
||||
/**
|
||||
* @type object
|
||||
*/
|
||||
@@ -5736,29 +5742,6 @@ export interface InframonitoringtypesNodeCountsByReadinessDTO {
|
||||
ready: number;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesPodCountsByPhaseDTO {
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
failed: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
pending: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
running: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
succeeded: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
unknown: number;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesPodCountsByStatusDTO {
|
||||
/**
|
||||
* @type integer
|
||||
@@ -5868,7 +5851,6 @@ export interface InframonitoringtypesClusterRecordDTO {
|
||||
*/
|
||||
meta: InframonitoringtypesClusterRecordDTOMeta;
|
||||
nodeCountsByReadiness: InframonitoringtypesNodeCountsByReadinessDTO;
|
||||
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
|
||||
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
|
||||
}
|
||||
|
||||
@@ -6144,7 +6126,6 @@ export interface InframonitoringtypesDaemonSetRecordDTO {
|
||||
* @type integer
|
||||
*/
|
||||
misscheduledNodes: number;
|
||||
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
|
||||
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -6226,7 +6207,6 @@ export interface InframonitoringtypesDeploymentRecordDTO {
|
||||
* @type object,null
|
||||
*/
|
||||
meta: InframonitoringtypesDeploymentRecordDTOMeta;
|
||||
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
|
||||
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
|
||||
}
|
||||
|
||||
@@ -6393,7 +6373,6 @@ export interface InframonitoringtypesJobRecordDTO {
|
||||
* @type object,null
|
||||
*/
|
||||
meta: InframonitoringtypesJobRecordDTOMeta;
|
||||
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
|
||||
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -6474,7 +6453,6 @@ export interface InframonitoringtypesNamespaceRecordDTO {
|
||||
* @type string
|
||||
*/
|
||||
namespaceName: string;
|
||||
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
|
||||
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
|
||||
}
|
||||
|
||||
@@ -6541,7 +6519,6 @@ export interface InframonitoringtypesNodeRecordDTO {
|
||||
* @type string
|
||||
*/
|
||||
nodeName: string;
|
||||
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
|
||||
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
|
||||
}
|
||||
|
||||
@@ -6562,14 +6539,6 @@ export interface InframonitoringtypesNodesDTO {
|
||||
warning?: Querybuildertypesv5QueryWarnDataDTO;
|
||||
}
|
||||
|
||||
export enum InframonitoringtypesPodPhaseDTO {
|
||||
pending = 'pending',
|
||||
running = 'running',
|
||||
succeeded = 'succeeded',
|
||||
failed = 'failed',
|
||||
unknown = 'unknown',
|
||||
no_data = 'no_data',
|
||||
}
|
||||
export type InframonitoringtypesPodRecordDTOMetaAnyOf = {
|
||||
[key: string]: string;
|
||||
};
|
||||
@@ -6626,7 +6595,6 @@ export interface InframonitoringtypesPodRecordDTO {
|
||||
* @format double
|
||||
*/
|
||||
podCPURequest: number;
|
||||
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
|
||||
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
|
||||
/**
|
||||
* @type number
|
||||
@@ -6643,7 +6611,6 @@ export interface InframonitoringtypesPodRecordDTO {
|
||||
* @format double
|
||||
*/
|
||||
podMemoryRequest: number;
|
||||
podPhase: InframonitoringtypesPodPhaseDTO;
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
@@ -6993,7 +6960,6 @@ export interface InframonitoringtypesStatefulSetRecordDTO {
|
||||
* @type object,null
|
||||
*/
|
||||
meta: InframonitoringtypesStatefulSetRecordDTOMeta;
|
||||
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
|
||||
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
|
||||
/**
|
||||
* @type number
|
||||
|
||||
@@ -1,26 +1,50 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { AxiosError, AxiosResponse } from 'axios';
|
||||
import { ErrorV2Resp } from 'types/api';
|
||||
import { ExportRawDataProps } from 'types/api/exportRawData/getExportRawData';
|
||||
|
||||
export interface FetchExportDataProps extends ExportRawDataProps {
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
|
||||
async function postExportRawData({
|
||||
format,
|
||||
body,
|
||||
signal,
|
||||
}: FetchExportDataProps): Promise<AxiosResponse<Blob>> {
|
||||
return axios.post<Blob>(
|
||||
`export_raw_data?format=${encodeURIComponent(format)}`,
|
||||
body,
|
||||
{
|
||||
responseType: 'blob',
|
||||
decompress: true,
|
||||
headers: {
|
||||
Accept: 'application/octet-stream',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
timeout: 0,
|
||||
signal,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a single export_raw_data page and returns it as a Blob.
|
||||
* Callers own retry/cancel/error UX.
|
||||
*/
|
||||
export async function fetchExportData(
|
||||
props: FetchExportDataProps,
|
||||
): Promise<Blob> {
|
||||
const response = await postExportRawData(props);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export const downloadExportData = async (
|
||||
props: ExportRawDataProps,
|
||||
): Promise<void> => {
|
||||
try {
|
||||
const response = await axios.post<Blob>(
|
||||
`export_raw_data?format=${encodeURIComponent(props.format)}`,
|
||||
props.body,
|
||||
{
|
||||
responseType: 'blob',
|
||||
decompress: true,
|
||||
headers: {
|
||||
Accept: 'application/octet-stream',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
timeout: 0,
|
||||
},
|
||||
);
|
||||
const response = await postExportRawData(props);
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw new Error(
|
||||
|
||||
@@ -52,6 +52,8 @@ import type { SignalType } from 'types/api/v5/queryRange';
|
||||
import { queryExamples, SUGGESTIONS_SECTION } from './constants';
|
||||
import {
|
||||
combineInitialAndUserExpression,
|
||||
dedupeOptionsByLabel,
|
||||
getFieldContextPrefix,
|
||||
getRecentOptions,
|
||||
renderRecentDeleteButton,
|
||||
} from './utils';
|
||||
@@ -222,6 +224,12 @@ function QuerySearch({
|
||||
QueryKeyDataSuggestionsProps[] | null
|
||||
>(null);
|
||||
|
||||
// dedupe keySuggestions by label/name
|
||||
const dedupedKeySuggestions = useMemo(
|
||||
() => dedupeOptionsByLabel(keySuggestions || []),
|
||||
[keySuggestions],
|
||||
);
|
||||
|
||||
const [showExamples] = useState(false);
|
||||
|
||||
const [cursorPos, setCursorPos] = useState({ line: 0, ch: 0 });
|
||||
@@ -246,9 +254,11 @@ function QuerySearch({
|
||||
[key: string]: QueryKeyDataSuggestionsProps[];
|
||||
}): any[] =>
|
||||
Object.values(keys).flatMap((items: QueryKeyDataSuggestionsProps[]) =>
|
||||
items.map(({ name, fieldDataType }) => ({
|
||||
items.map(({ name, fieldDataType, fieldContext }) => ({
|
||||
label: name,
|
||||
type: fieldDataType === 'string' ? 'keyword' : fieldDataType,
|
||||
fieldContext,
|
||||
fieldDataType,
|
||||
info: '',
|
||||
details: '',
|
||||
})),
|
||||
@@ -307,13 +317,17 @@ function QuerySearch({
|
||||
if (response.data.data) {
|
||||
const { keys } = response.data.data;
|
||||
const options = generateOptions(keys);
|
||||
// Use a Map to deduplicate by label and preserve order: new options take precedence
|
||||
// Deduplicate by full variant identity (name + context + data type), NOT by
|
||||
// label. deduping by label removes varient which is not expected. If we need
|
||||
// to dedupe by label use dedupedKeySuggestions not dedupe the source itself
|
||||
const variantId = (opt: QueryKeyDataSuggestionsProps): string =>
|
||||
`${opt.label}|${opt.fieldContext ?? ''}|${opt.fieldDataType ?? ''}`;
|
||||
const merged = new Map<string, QueryKeyDataSuggestionsProps>();
|
||||
options.forEach((opt) => merged.set(opt.label, opt));
|
||||
options.forEach((opt) => merged.set(variantId(opt), opt));
|
||||
if (searchText && lastKeyRef.current !== searchText) {
|
||||
(keySuggestions || []).forEach((opt) => {
|
||||
if (!merged.has(opt.label)) {
|
||||
merged.set(opt.label, opt);
|
||||
if (!merged.has(variantId(opt))) {
|
||||
merged.set(variantId(opt), opt);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -919,8 +933,55 @@ function QuerySearch({
|
||||
|
||||
if (queryContext.isInKey) {
|
||||
const searchText = word?.text.toLowerCase().trim() ?? '';
|
||||
const fieldContextMatch = getFieldContextPrefix(searchText);
|
||||
|
||||
options = (keySuggestions || []).filter((option) =>
|
||||
if (fieldContextMatch) {
|
||||
const { context: fieldContext, remainder } = fieldContextMatch;
|
||||
|
||||
// Fetch the context's page when the prefix is typed exactly eg.("attribute.")
|
||||
if (remainder === '' && lastFetchedKeyRef.current !== searchText) {
|
||||
debouncedFetchKeySuggestions(searchText);
|
||||
}
|
||||
|
||||
//suggestions that actually do start with <fieldContext>.
|
||||
const nameMatches = (keySuggestions || [])
|
||||
.filter((option) => option.label.toLowerCase().includes(searchText))
|
||||
.map((option) => ({ ...option, boost: 100 }));
|
||||
|
||||
//suggestions which do not start with the prefix but qualifies for suggestion
|
||||
const contextQualified = (keySuggestions || [])
|
||||
.filter(
|
||||
(option) =>
|
||||
option.fieldContext === fieldContext &&
|
||||
option.label.toLowerCase().includes(remainder),
|
||||
)
|
||||
.map((option) => ({
|
||||
...option,
|
||||
label: `${fieldContext}.${option.label}`,
|
||||
boost: 0,
|
||||
}));
|
||||
|
||||
const contextOptions = dedupeOptionsByLabel([
|
||||
...nameMatches,
|
||||
...contextQualified,
|
||||
]);
|
||||
|
||||
// If contextOptions is empty fetch again.
|
||||
if (
|
||||
contextOptions.length === 0 &&
|
||||
lastFetchedKeyRef.current !== searchText
|
||||
) {
|
||||
debouncedFetchKeySuggestions(searchText);
|
||||
}
|
||||
|
||||
return {
|
||||
from: word?.from ?? 0,
|
||||
to: word?.to ?? cursorPos.ch,
|
||||
options: addSpaceToOptions(contextOptions),
|
||||
};
|
||||
}
|
||||
|
||||
options = dedupedKeySuggestions.filter((option) =>
|
||||
option.label.toLowerCase().includes(searchText),
|
||||
);
|
||||
|
||||
@@ -969,9 +1030,26 @@ function QuerySearch({
|
||||
|
||||
// If we have a key context, add that info to the operator suggestions
|
||||
if (keyName) {
|
||||
// Find the key details from suggestions
|
||||
const keyDetails = (keySuggestions || []).find((k) => k.label === keyName);
|
||||
const keyType = keyDetails?.type || '';
|
||||
const keyContextMatch = getFieldContextPrefix(keyName);
|
||||
// key-suggestion can contain multiple variants of a single key
|
||||
// In variants we capture ones that match the label to typed keyName exactly or,
|
||||
// if it has a prefix fieldContext remove it and then match.
|
||||
const variants = (keySuggestions || []).filter(
|
||||
(k) =>
|
||||
k.label === keyName ||
|
||||
(keyContextMatch !== null &&
|
||||
k.fieldContext === keyContextMatch.context &&
|
||||
k.label === keyContextMatch.remainder),
|
||||
);
|
||||
const variantTypes = new Set(
|
||||
variants
|
||||
.map((k) =>
|
||||
k.type === 'keyword' ? QUERY_BUILDER_KEY_TYPES.STRING : k.type,
|
||||
)
|
||||
.filter(Boolean),
|
||||
);
|
||||
//if there are multi-variant, show all suggestions else just the one
|
||||
const keyType = variantTypes.size === 1 ? [...variantTypes][0] : '';
|
||||
|
||||
// Filter operators based on key type
|
||||
if (keyType) {
|
||||
@@ -1214,7 +1292,7 @@ function QuerySearch({
|
||||
if (curChar === '(') {
|
||||
// In expression context, suggest keys, functions, or nested parentheses
|
||||
options = [
|
||||
...(keySuggestions || []),
|
||||
...dedupedKeySuggestions,
|
||||
{ label: '(', type: 'parenthesis', info: 'Open nested group' },
|
||||
{ label: 'NOT', type: 'operator', info: 'Negate expression' },
|
||||
...options.filter((opt) => opt.type === 'function'),
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
import {
|
||||
combineInitialAndUserExpression,
|
||||
dedupeOptionsByLabel,
|
||||
getFieldContextPrefix,
|
||||
getUserExpressionFromCombined,
|
||||
} from '../utils';
|
||||
|
||||
describe('entityLogsExpression', () => {
|
||||
describe('combineInitialAndUserExpression', () => {
|
||||
it('returns user when initial is empty', () => {
|
||||
expect(combineInitialAndUserExpression('', 'body contains error')).toBe(
|
||||
'body contains error',
|
||||
);
|
||||
});
|
||||
|
||||
it('returns initial when user is empty', () => {
|
||||
expect(combineInitialAndUserExpression('k8s.pod.name = "x"', '')).toBe(
|
||||
'k8s.pod.name = "x"',
|
||||
);
|
||||
});
|
||||
|
||||
it('wraps user in parentheses with AND', () => {
|
||||
expect(
|
||||
combineInitialAndUserExpression('k8s.pod.name = "x"', 'body = "a"'),
|
||||
).toBe('k8s.pod.name = "x" AND (body = "a")');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getUserExpressionFromCombined', () => {
|
||||
it('returns empty when combined equals initial', () => {
|
||||
expect(
|
||||
getUserExpressionFromCombined('k8s.pod.name = "x"', 'k8s.pod.name = "x"'),
|
||||
).toBe('');
|
||||
});
|
||||
|
||||
it('extracts user from wrapped form', () => {
|
||||
expect(
|
||||
getUserExpressionFromCombined(
|
||||
'k8s.pod.name = "x"',
|
||||
'k8s.pod.name = "x" AND (body = "a")',
|
||||
),
|
||||
).toBe('body = "a"');
|
||||
});
|
||||
|
||||
it('extracts user from legacy AND without parens', () => {
|
||||
expect(
|
||||
getUserExpressionFromCombined(
|
||||
'k8s.pod.name = "x"',
|
||||
'k8s.pod.name = "x" AND body = "a"',
|
||||
),
|
||||
).toBe('body = "a"');
|
||||
});
|
||||
|
||||
it('returns full combined when initial is empty', () => {
|
||||
expect(getUserExpressionFromCombined('', 'service.name = "a"')).toBe(
|
||||
'service.name = "a"',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getFieldContextPrefix', () => {
|
||||
it('matches a complete context prefix with a remainder', () => {
|
||||
expect(getFieldContextPrefix('attribute.status')).toStrictEqual({
|
||||
context: 'attribute',
|
||||
remainder: 'status',
|
||||
});
|
||||
});
|
||||
|
||||
it('matches a bare context prefix with empty remainder', () => {
|
||||
expect(getFieldContextPrefix('resource.')).toStrictEqual({
|
||||
context: 'resource',
|
||||
remainder: '',
|
||||
});
|
||||
});
|
||||
|
||||
it('matches every backend field context', () => {
|
||||
['attribute', 'resource', 'span', 'body', 'log', 'metric'].forEach((ctx) => {
|
||||
expect(getFieldContextPrefix(`${ctx}.x`)).toStrictEqual({
|
||||
context: ctx,
|
||||
remainder: 'x',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('does not match a partial context name', () => {
|
||||
expect(getFieldContextPrefix('attr')).toBeNull();
|
||||
expect(getFieldContextPrefix('attribute')).toBeNull();
|
||||
});
|
||||
|
||||
it('does not match a non-context key with dots', () => {
|
||||
expect(getFieldContextPrefix('status.code')).toBeNull();
|
||||
});
|
||||
|
||||
it('matches context case-insensitively but keeps remainder casing', () => {
|
||||
expect(getFieldContextPrefix('Attribute.Status')).toStrictEqual({
|
||||
context: 'attribute',
|
||||
remainder: 'Status',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('dedupeOptionsByLabel', () => {
|
||||
it('keeps the first occurrence per label, preserving order', () => {
|
||||
expect(
|
||||
dedupeOptionsByLabel([
|
||||
{ label: 'status.code', type: 'keyword' },
|
||||
{ label: 'status.code', type: 'number' },
|
||||
{ label: 'duration', type: 'number' },
|
||||
]),
|
||||
).toStrictEqual([
|
||||
{ label: 'status.code', type: 'keyword' },
|
||||
{ label: 'duration', type: 'number' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns an empty array for empty input', () => {
|
||||
expect(dedupeOptionsByLabel([])).toStrictEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -1,58 +0,0 @@
|
||||
import {
|
||||
combineInitialAndUserExpression,
|
||||
getUserExpressionFromCombined,
|
||||
} from '../utils';
|
||||
|
||||
describe('entityLogsExpression', () => {
|
||||
describe('combineInitialAndUserExpression', () => {
|
||||
it('returns user when initial is empty', () => {
|
||||
expect(combineInitialAndUserExpression('', 'body contains error')).toBe(
|
||||
'body contains error',
|
||||
);
|
||||
});
|
||||
|
||||
it('returns initial when user is empty', () => {
|
||||
expect(combineInitialAndUserExpression('k8s.pod.name = "x"', '')).toBe(
|
||||
'k8s.pod.name = "x"',
|
||||
);
|
||||
});
|
||||
|
||||
it('wraps user in parentheses with AND', () => {
|
||||
expect(
|
||||
combineInitialAndUserExpression('k8s.pod.name = "x"', 'body = "a"'),
|
||||
).toBe('k8s.pod.name = "x" AND (body = "a")');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getUserExpressionFromCombined', () => {
|
||||
it('returns empty when combined equals initial', () => {
|
||||
expect(
|
||||
getUserExpressionFromCombined('k8s.pod.name = "x"', 'k8s.pod.name = "x"'),
|
||||
).toBe('');
|
||||
});
|
||||
|
||||
it('extracts user from wrapped form', () => {
|
||||
expect(
|
||||
getUserExpressionFromCombined(
|
||||
'k8s.pod.name = "x"',
|
||||
'k8s.pod.name = "x" AND (body = "a")',
|
||||
),
|
||||
).toBe('body = "a"');
|
||||
});
|
||||
|
||||
it('extracts user from legacy AND without parens', () => {
|
||||
expect(
|
||||
getUserExpressionFromCombined(
|
||||
'k8s.pod.name = "x"',
|
||||
'k8s.pod.name = "x" AND body = "a"',
|
||||
),
|
||||
).toBe('body = "a"');
|
||||
});
|
||||
|
||||
it('returns full combined when initial is empty', () => {
|
||||
expect(getUserExpressionFromCombined('', 'service.name = "a"')).toBe(
|
||||
'service.name = "a"',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,16 @@
|
||||
export const RECENTS_SECTION = { name: 'Recent searches', rank: 1 } as const;
|
||||
export const SUGGESTIONS_SECTION = { name: 'Suggestions', rank: 2 } as const;
|
||||
|
||||
// TODO: move to using TelemetrytypesFieldContextDTO when we migrate getKeySuggestions API (Part of https://github.com/SigNoz/engineering-pod/issues/5289)
|
||||
export const FIELD_CONTEXTS = [
|
||||
'attribute',
|
||||
'resource',
|
||||
'span',
|
||||
'body',
|
||||
'log',
|
||||
'metric',
|
||||
] as const;
|
||||
|
||||
// Custom CodeMirror Completion.type for recent-query entries. Used to discriminate
|
||||
// recents from regular autocomplete completions in renderers and event handlers.
|
||||
export const RECENT_COMPLETION_TYPE = 'recent';
|
||||
|
||||
@@ -9,11 +9,45 @@ import type { SignalType } from 'types/api/v5/queryRange';
|
||||
import 'utils/timeUtils';
|
||||
|
||||
import {
|
||||
FIELD_CONTEXTS,
|
||||
RECENT_COMPLETION_TYPE,
|
||||
RECENTS_DISPLAY_CAP,
|
||||
RECENTS_SECTION,
|
||||
} from './constants';
|
||||
|
||||
export interface FieldContextPrefixMatch {
|
||||
context: string;
|
||||
remainder: string;
|
||||
}
|
||||
|
||||
// This function checks if the text(query key) starts with a fieldContext
|
||||
// This util strictly checks that and returns context and remainder back.
|
||||
// This helps differentiate if the typed key was prefixed with a context or
|
||||
// was it an actual queryKey like (attribute.abc)
|
||||
export function getFieldContextPrefix(
|
||||
text: string,
|
||||
): FieldContextPrefixMatch | null {
|
||||
const lower = text.toLowerCase();
|
||||
const context = FIELD_CONTEXTS.find((ctx) => lower.startsWith(`${ctx}.`));
|
||||
return context ? { context, remainder: text.slice(context.length + 1) } : null;
|
||||
}
|
||||
|
||||
// Keeps the first occurrence per label, preserving order. Key suggestions hold
|
||||
// one entry per (name, fieldContext, fieldDataType) variant; This means query builder
|
||||
// could show multiple labels and this avoids that.
|
||||
export function dedupeOptionsByLabel<T extends { label: string }>(
|
||||
options: T[],
|
||||
): T[] {
|
||||
const seen = new Set<string>();
|
||||
return options.filter((option) => {
|
||||
if (seen.has(option.label)) {
|
||||
return false;
|
||||
}
|
||||
seen.add(option.label);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
export function combineInitialAndUserExpression(
|
||||
initial: string,
|
||||
user: string,
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
import { initialQueriesMap } from 'constants/queryBuilder';
|
||||
import { rest, server } from 'mocks-server/server';
|
||||
import { render, userEvent, waitFor } from 'tests/test-utils';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import QuerySearch from '../QuerySearch/QuerySearch';
|
||||
import { mockCodeMirrorDomApis } from './codemirrorDomMocks';
|
||||
|
||||
const CM_EDITOR_SELECTOR = '.cm-editor .cm-content';
|
||||
const CM_OPTION_SELECTOR = '.cm-tooltip-autocomplete .cm-completionLabel';
|
||||
|
||||
beforeAll(() => {
|
||||
mockCodeMirrorDomApis();
|
||||
});
|
||||
|
||||
jest.mock('hooks/useDarkMode', () => ({
|
||||
useIsDarkMode: (): boolean => false,
|
||||
}));
|
||||
|
||||
jest.mock('providers/Dashboard/store/useDashboardStore', () => ({
|
||||
useDashboardStore: (): { dashboardData: undefined } => ({
|
||||
dashboardData: undefined,
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('hooks/queryBuilder/useQueryBuilder', () => {
|
||||
const handleRunQuery = jest.fn();
|
||||
return {
|
||||
__esModule: true,
|
||||
useQueryBuilder: (): { handleRunQuery: () => void } => ({ handleRunQuery }),
|
||||
handleRunQuery,
|
||||
};
|
||||
});
|
||||
|
||||
// Keys fixture: status.code exists as 3 variants (attribute string/number +
|
||||
// resource string); attribute.a.b.c is a key literally named with the prefix.
|
||||
const KEYS_FIXTURE = {
|
||||
'status.code': [
|
||||
{
|
||||
name: 'status.code',
|
||||
fieldContext: 'attribute',
|
||||
fieldDataType: 'string',
|
||||
signal: 'logs',
|
||||
},
|
||||
{
|
||||
name: 'status.code',
|
||||
fieldContext: 'attribute',
|
||||
fieldDataType: 'number',
|
||||
signal: 'logs',
|
||||
},
|
||||
{
|
||||
name: 'status.code',
|
||||
fieldContext: 'resource',
|
||||
fieldDataType: 'string',
|
||||
signal: 'logs',
|
||||
},
|
||||
],
|
||||
'attribute.a.b.c': [
|
||||
{
|
||||
name: 'attribute.a.b.c',
|
||||
fieldContext: 'attribute',
|
||||
fieldDataType: 'string',
|
||||
signal: 'logs',
|
||||
},
|
||||
],
|
||||
'duration.nano': [
|
||||
{
|
||||
name: 'duration.nano',
|
||||
fieldContext: 'span',
|
||||
fieldDataType: 'number',
|
||||
signal: 'logs',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const fetchedSearchTexts: string[] = [];
|
||||
|
||||
beforeEach(() => {
|
||||
fetchedSearchTexts.length = 0;
|
||||
server.use(
|
||||
rest.get('http://localhost/api/v1/fields/keys', (req, res, ctx) => {
|
||||
fetchedSearchTexts.push(req.url.searchParams.get('searchText') ?? '');
|
||||
return res(
|
||||
ctx.status(200),
|
||||
ctx.json({
|
||||
status: 'success',
|
||||
data: { complete: true, keys: KEYS_FIXTURE },
|
||||
}),
|
||||
);
|
||||
}),
|
||||
rest.get('http://localhost/api/v1/fields/values', (_req, res, ctx) =>
|
||||
res(
|
||||
ctx.status(200),
|
||||
ctx.json({
|
||||
status: 'success',
|
||||
data: { values: { stringValues: [], numberValues: [] } },
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
async function renderAndType(text: string): Promise<HTMLElement> {
|
||||
render(
|
||||
<QuerySearch
|
||||
onChange={jest.fn() as jest.MockedFunction<(v: string) => void>}
|
||||
queryData={initialQueriesMap.logs.builder.queryData[0]}
|
||||
dataSource={DataSource.LOGS}
|
||||
/>,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(document.querySelector(CM_EDITOR_SELECTOR)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const editor = document.querySelector(CM_EDITOR_SELECTOR) as HTMLElement;
|
||||
await userEvent.click(editor);
|
||||
await userEvent.type(editor, text);
|
||||
return editor;
|
||||
}
|
||||
|
||||
// Types a key, waits for its suggestion to render (proving the debounced key
|
||||
// fetch resolved into state), then types a space to enter operator context.
|
||||
async function typeKeyThenEnterOperatorContext(
|
||||
key: string,
|
||||
expectedKeyLabel: string,
|
||||
): Promise<void> {
|
||||
const editor = await renderAndType(key);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(visibleOptionLabels()).toContain(expectedKeyLabel);
|
||||
});
|
||||
|
||||
// skipClick: a click would reset the caret to position 0 under the mocked
|
||||
// DOM rects; we need the space appended at the end of the typed key.
|
||||
await userEvent.type(editor, ' ', { skipClick: true });
|
||||
|
||||
await waitFor(() => {
|
||||
expect(visibleOptionLabels()).toContain('=');
|
||||
});
|
||||
}
|
||||
|
||||
function visibleOptionLabels(): string[] {
|
||||
return Array.from(document.querySelectorAll(CM_OPTION_SELECTOR)).map(
|
||||
(el) => el.textContent ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
describe('QuerySearch context-prefixed key suggestions', () => {
|
||||
it('shows one deduped suggestion per key name in normal mode', async () => {
|
||||
await renderAndType('statu');
|
||||
|
||||
await waitFor(() => {
|
||||
expect(visibleOptionLabels()).toContain('status.code');
|
||||
});
|
||||
|
||||
const statusOptions = visibleOptionLabels().filter(
|
||||
(label) => label === 'status.code',
|
||||
);
|
||||
expect(statusOptions).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('shows context-scoped suggestions for a complete context prefix', async () => {
|
||||
await renderAndType('attribute.');
|
||||
|
||||
await waitFor(() => {
|
||||
expect(visibleOptionLabels()).toContain('attribute.status.code');
|
||||
});
|
||||
|
||||
const labels = visibleOptionLabels();
|
||||
// Literal key name match ranks first
|
||||
expect(labels[0]).toBe('attribute.a.b.c');
|
||||
// Context-qualified form of the literal key is also present
|
||||
expect(labels).toContain('attribute.attribute.a.b.c');
|
||||
// span-only key is not suggested under attribute.
|
||||
expect(labels).not.toContain('attribute.duration.nano');
|
||||
});
|
||||
|
||||
it('fetches the context page when the prefix is typed exactly', async () => {
|
||||
await renderAndType('attribute.');
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchedSearchTexts).toContain('attribute.');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('QuerySearch operator suggestions by key type', () => {
|
||||
it('shows all operators for a key with ambiguous types', async () => {
|
||||
// status.code is string + number across variants → no type filtering
|
||||
await typeKeyThenEnterOperatorContext('status.code', 'status.code');
|
||||
|
||||
const labels = visibleOptionLabels();
|
||||
expect(labels).toContain('>');
|
||||
expect(labels).toContain('LIKE');
|
||||
});
|
||||
|
||||
it('shows numeric operators for a single-type number key', async () => {
|
||||
await typeKeyThenEnterOperatorContext('duration.nano', 'duration.nano');
|
||||
|
||||
const labels = visibleOptionLabels();
|
||||
expect(labels).toContain('>');
|
||||
expect(labels).not.toContain('LIKE');
|
||||
});
|
||||
|
||||
it('narrows operators when a context prefix disambiguates the type', async () => {
|
||||
// status.code is ambiguous globally, but resource.status.code is string-only
|
||||
await typeKeyThenEnterOperatorContext(
|
||||
'resource.status.code',
|
||||
'resource.status.code',
|
||||
);
|
||||
|
||||
const labels = visibleOptionLabels();
|
||||
expect(labels).toContain('LIKE');
|
||||
expect(labels).not.toContain('>');
|
||||
});
|
||||
});
|
||||
@@ -8,78 +8,13 @@ import type { QueryKeyDataSuggestionsProps } from 'types/api/querySuggestions/ty
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import QuerySearch from '../QuerySearch/QuerySearch';
|
||||
import { mockCodeMirrorDomApis } from './codemirrorDomMocks';
|
||||
|
||||
const CM_EDITOR_SELECTOR = '.cm-editor .cm-content';
|
||||
|
||||
// Mock DOM APIs that CodeMirror needs
|
||||
beforeAll(() => {
|
||||
// Mock getClientRects and getBoundingClientRect for Range objects
|
||||
const mockRect: DOMRect = {
|
||||
width: 100,
|
||||
height: 20,
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 100,
|
||||
bottom: 20,
|
||||
x: 0,
|
||||
y: 0,
|
||||
toJSON: (): DOMRect => mockRect,
|
||||
} as DOMRect;
|
||||
|
||||
// Create a minimal Range mock with only what CodeMirror actually uses
|
||||
const createMockRange = (): Range => {
|
||||
let startContainer: Node = document.createTextNode('');
|
||||
let endContainer: Node = document.createTextNode('');
|
||||
let startOffset = 0;
|
||||
let endOffset = 0;
|
||||
|
||||
const mockRange = {
|
||||
// CodeMirror uses these for text measurement
|
||||
getClientRects: (): DOMRectList =>
|
||||
({
|
||||
length: 1,
|
||||
item: (index: number): DOMRect | null => (index === 0 ? mockRect : null),
|
||||
0: mockRect,
|
||||
*[Symbol.iterator](): Generator<DOMRect> {
|
||||
yield mockRect;
|
||||
},
|
||||
}) as unknown as DOMRectList,
|
||||
getBoundingClientRect: (): DOMRect => mockRect,
|
||||
// CodeMirror calls these to set up text ranges
|
||||
setStart: (node: Node, offset: number): void => {
|
||||
startContainer = node;
|
||||
startOffset = offset;
|
||||
},
|
||||
setEnd: (node: Node, offset: number): void => {
|
||||
endContainer = node;
|
||||
endOffset = offset;
|
||||
},
|
||||
// Minimal Range properties (TypeScript requires these)
|
||||
get startContainer(): Node {
|
||||
return startContainer;
|
||||
},
|
||||
get endContainer(): Node {
|
||||
return endContainer;
|
||||
},
|
||||
get startOffset(): number {
|
||||
return startOffset;
|
||||
},
|
||||
get endOffset(): number {
|
||||
return endOffset;
|
||||
},
|
||||
get collapsed(): boolean {
|
||||
return startContainer === endContainer && startOffset === endOffset;
|
||||
},
|
||||
commonAncestorContainer: document.body,
|
||||
};
|
||||
return mockRange as unknown as Range;
|
||||
};
|
||||
|
||||
// Mock document.createRange to return a new Range instance each time
|
||||
document.createRange = (): Range => createMockRange();
|
||||
|
||||
// Mock getBoundingClientRect for elements
|
||||
Element.prototype.getBoundingClientRect = (): DOMRect => mockRect;
|
||||
mockCodeMirrorDomApis();
|
||||
});
|
||||
|
||||
jest.mock('hooks/useDarkMode', () => ({
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
// Mocks the DOM measurement APIs CodeMirror needs to render in jsdom
|
||||
// (Range client rects + element bounding rects). Call from a beforeAll in
|
||||
// specs that render the real CodeMirror editor.
|
||||
export function mockCodeMirrorDomApis(): void {
|
||||
const mockRect: DOMRect = {
|
||||
width: 100,
|
||||
height: 20,
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 100,
|
||||
bottom: 20,
|
||||
x: 0,
|
||||
y: 0,
|
||||
toJSON: (): DOMRect => mockRect,
|
||||
} as DOMRect;
|
||||
|
||||
// Create a minimal Range mock with only what CodeMirror actually uses
|
||||
const createMockRange = (): Range => {
|
||||
let startContainer: Node = document.createTextNode('');
|
||||
let endContainer: Node = document.createTextNode('');
|
||||
let startOffset = 0;
|
||||
let endOffset = 0;
|
||||
|
||||
const mockRange = {
|
||||
// CodeMirror uses these for text measurement
|
||||
getClientRects: (): DOMRectList =>
|
||||
({
|
||||
length: 1,
|
||||
item: (index: number): DOMRect | null => (index === 0 ? mockRect : null),
|
||||
0: mockRect,
|
||||
*[Symbol.iterator](): Generator<DOMRect> {
|
||||
yield mockRect;
|
||||
},
|
||||
}) as unknown as DOMRectList,
|
||||
getBoundingClientRect: (): DOMRect => mockRect,
|
||||
// CodeMirror calls these to set up text ranges
|
||||
setStart: (node: Node, offset: number): void => {
|
||||
startContainer = node;
|
||||
startOffset = offset;
|
||||
},
|
||||
setEnd: (node: Node, offset: number): void => {
|
||||
endContainer = node;
|
||||
endOffset = offset;
|
||||
},
|
||||
// Minimal Range properties (TypeScript requires these)
|
||||
get startContainer(): Node {
|
||||
return startContainer;
|
||||
},
|
||||
get endContainer(): Node {
|
||||
return endContainer;
|
||||
},
|
||||
get startOffset(): number {
|
||||
return startOffset;
|
||||
},
|
||||
get endOffset(): number {
|
||||
return endOffset;
|
||||
},
|
||||
get collapsed(): boolean {
|
||||
return startContainer === endContainer && startOffset === endOffset;
|
||||
},
|
||||
commonAncestorContainer: document.body,
|
||||
};
|
||||
return mockRange as unknown as Range;
|
||||
};
|
||||
|
||||
// Mock document.createRange to return a new Range instance each time
|
||||
document.createRange = (): Range => createMockRange();
|
||||
|
||||
// Mock getBoundingClientRect for elements
|
||||
Element.prototype.getBoundingClientRect = (): DOMRect => mockRect;
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import { extractQueryPairs } from 'utils/queryContextUtils';
|
||||
|
||||
import {
|
||||
convertAggregationToExpression,
|
||||
convertExpressionToFilters,
|
||||
convertFiltersToExpression,
|
||||
convertFiltersToExpressionWithExistingQuery,
|
||||
formatValueForExpression,
|
||||
@@ -1598,4 +1599,36 @@ describe('formatValueForExpression', () => {
|
||||
expect(formatValueForExpression([123] as any)).toBe('[123]');
|
||||
});
|
||||
});
|
||||
|
||||
// Regression: an escaped single quote must not gain a backslash on each
|
||||
// expression <-> filters round-trip (broke Create Alert from a panel).
|
||||
describe('escaped quote round-trip', () => {
|
||||
const EXPR = "name = 'it\\'s a ribbon'"; // name = 'it\'s a ribbon' (single backslash)
|
||||
|
||||
it('stores the unescaped value in the filter item', () => {
|
||||
const items = convertExpressionToFilters(EXPR);
|
||||
expect(items).toHaveLength(1);
|
||||
expect(items[0].value).toBe("it's a ribbon");
|
||||
});
|
||||
|
||||
it('is lossless: expression -> filters -> expression', () => {
|
||||
const items = convertExpressionToFilters(EXPR);
|
||||
expect(convertFiltersToExpression({ items, op: 'AND' }).expression).toBe(
|
||||
EXPR,
|
||||
);
|
||||
});
|
||||
|
||||
it('is idempotent across repeated existing-query conversions', () => {
|
||||
const pass1 = convertFiltersToExpressionWithExistingQuery(
|
||||
{ items: [], op: 'AND' },
|
||||
EXPR,
|
||||
);
|
||||
expect(pass1.filter.expression).toBe(EXPR);
|
||||
const pass2 = convertFiltersToExpressionWithExistingQuery(
|
||||
pass1.filters,
|
||||
pass1.filter.expression,
|
||||
);
|
||||
expect(pass2.filter.expression).toBe(EXPR);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -176,7 +176,9 @@ function formatSingleValueForFilter(
|
||||
}
|
||||
|
||||
if (isQuoted(value)) {
|
||||
return unquote(value);
|
||||
// Unescape `\'` → `'` (inverse of formatSingleValue) so the round-trip doesn't
|
||||
// double the backslash each pass.
|
||||
return unquote(value).replace(/\\'/g, "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,4 +65,5 @@
|
||||
min-width: 0;
|
||||
padding-left: 12px;
|
||||
padding-bottom: 12px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
@@ -25,20 +25,52 @@ describe('calculateChartDimensions', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('RIGHT: reserves a side column capped at 30% of the width and keeps full height', () => {
|
||||
it('RIGHT: reserves a side column capped at 320px / 40% of the width and keeps full height', () => {
|
||||
const dims = calculateChartDimensions({
|
||||
containerWidth: 1000,
|
||||
containerHeight: 400,
|
||||
legendConfig: { position: LegendPosition.RIGHT },
|
||||
seriesLabels: labels(10, 40),
|
||||
});
|
||||
// 40-char labels approximate to 336px, capped at min(240, 30% of 1000).
|
||||
expect(dims.legendWidth).toBe(240);
|
||||
expect(dims.width).toBe(760);
|
||||
expect(dims.legendWidth).toBe(320);
|
||||
expect(dims.width).toBe(680);
|
||||
expect(dims.height).toBe(400);
|
||||
expect(dims.legendHeight).toBe(400);
|
||||
});
|
||||
|
||||
it('RIGHT: sizes the column to the longest label when it fits under the cap', () => {
|
||||
const dims = calculateChartDimensions({
|
||||
containerWidth: 1000,
|
||||
containerHeight: 400,
|
||||
legendConfig: { position: LegendPosition.RIGHT },
|
||||
seriesLabels: labels(5, 20),
|
||||
});
|
||||
expect(dims.legendWidth).toBe(216);
|
||||
expect(dims.width).toBe(784);
|
||||
});
|
||||
|
||||
it('RIGHT: never shrinks the column below the 150px floor', () => {
|
||||
const dims = calculateChartDimensions({
|
||||
containerWidth: 1000,
|
||||
containerHeight: 400,
|
||||
legendConfig: { position: LegendPosition.RIGHT },
|
||||
seriesLabels: labels(3, 3),
|
||||
});
|
||||
expect(dims.legendWidth).toBe(150);
|
||||
expect(dims.width).toBe(850);
|
||||
});
|
||||
|
||||
it('RIGHT: on a narrow container the legend never takes more than 40% of the width', () => {
|
||||
const dims = calculateChartDimensions({
|
||||
containerWidth: 300,
|
||||
containerHeight: 400,
|
||||
legendConfig: { position: LegendPosition.RIGHT },
|
||||
seriesLabels: labels(10, 40),
|
||||
});
|
||||
expect(dims.legendWidth).toBe(120);
|
||||
expect(dims.width).toBe(180);
|
||||
});
|
||||
|
||||
it('BOTTOM: a single row of items reserves one legend row', () => {
|
||||
const dims = calculateChartDimensions({
|
||||
containerWidth: 1000,
|
||||
|
||||
@@ -15,6 +15,12 @@ const BASE_LEGEND_WIDTH = 16;
|
||||
const LEGEND_PADDING = 12;
|
||||
const LEGEND_LINE_HEIGHT = 28;
|
||||
|
||||
// RIGHT legend is a vertical column with its own width budget (cap protects the donut).
|
||||
const MAX_RIGHT_LEGEND_WIDTH = 320;
|
||||
const RIGHT_LEGEND_WIDTH_RATIO = 0.4;
|
||||
// Column padding + copy button, not covered by the text-length estimate.
|
||||
const RIGHT_LEGEND_RESERVED_WIDTH = 40;
|
||||
|
||||
/**
|
||||
* Calculates the average width of the legend items based on the labels of the series.
|
||||
* @param legends - The labels of the series.
|
||||
@@ -42,7 +48,7 @@ export function calculateAverageLegendWidth(legends: string[]): number {
|
||||
* Implementation details (high level):
|
||||
* - Approximates legend item width from label text length, using a fixed average char width.
|
||||
* - RIGHT legend:
|
||||
* - `legendWidth` is clamped between 150px and min(MAX_LEGEND_WIDTH, 30% of container width).
|
||||
* - `legendWidth` fits the longest label, clamped to [150px, min(MAX_RIGHT_LEGEND_WIDTH, 40% width)].
|
||||
* - Chart width is `containerWidth - legendWidth`.
|
||||
* - BOTTOM legend:
|
||||
* - Computes how many items fit per row, then uses at most 2 rows.
|
||||
@@ -80,9 +86,22 @@ export function calculateChartDimensions({
|
||||
const legendItemCount = seriesLabels.length;
|
||||
|
||||
if (legendConfig.position === LegendPosition.RIGHT) {
|
||||
const maxRightLegendWidth = Math.min(MAX_LEGEND_WIDTH, containerWidth * 0.3);
|
||||
// Size the column to the longest name (up to the cap) so it doesn't ellipsize.
|
||||
const longestLabelLength = seriesLabels.reduce(
|
||||
(max, label) => Math.max(max, label.length),
|
||||
0,
|
||||
);
|
||||
const desiredLegendWidth =
|
||||
BASE_LEGEND_WIDTH +
|
||||
longestLabelLength * AVG_CHAR_WIDTH +
|
||||
RIGHT_LEGEND_RESERVED_WIDTH;
|
||||
|
||||
const maxRightLegendWidth = Math.min(
|
||||
MAX_RIGHT_LEGEND_WIDTH,
|
||||
containerWidth * RIGHT_LEGEND_WIDTH_RATIO,
|
||||
);
|
||||
const rightLegendWidth = Math.min(
|
||||
Math.max(150, approxLegendItemWidth),
|
||||
Math.max(150, desiredLegendWidth),
|
||||
maxRightLegendWidth,
|
||||
);
|
||||
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
|
||||
&--legend-right {
|
||||
flex-direction: row;
|
||||
|
||||
.chart-layout__legend-wrapper {
|
||||
padding-top: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&__legend-wrapper {
|
||||
|
||||
@@ -15,7 +15,6 @@ import APIError from 'types/api/error';
|
||||
import QuickFilters from 'components/QuickFilters/QuickFilters';
|
||||
import { QuickFiltersSource } from 'components/QuickFilters/types';
|
||||
import { InfraMonitoringEvents } from 'constants/events';
|
||||
import { FeatureKeys } from 'constants/features';
|
||||
import { initialQueriesMap } from 'constants/queryBuilder';
|
||||
import K8sBaseDetails, {
|
||||
K8sDetailsFilters,
|
||||
@@ -29,7 +28,6 @@ import {
|
||||
} from 'container/InfraMonitoringK8sV2/constants';
|
||||
import { useGetCompositeQueryParam } from 'hooks/queryBuilder/useGetCompositeQueryParam';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import {
|
||||
@@ -93,11 +91,6 @@ function Hosts(): JSX.Element {
|
||||
}
|
||||
}, [compositeQuery, redirectWithQueryBuilderData]);
|
||||
|
||||
const { featureFlags } = useAppContext();
|
||||
const dotMetricsEnabled =
|
||||
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||
?.active || false;
|
||||
|
||||
const handleFilterVisibilityChange = (): void => {
|
||||
setShowFilters(!showFilters);
|
||||
};
|
||||
@@ -190,8 +183,8 @@ function Hosts(): JSX.Element {
|
||||
|
||||
const getInitialLogTracesExpression = useCallback(
|
||||
(host: InframonitoringtypesHostRecordDTO) =>
|
||||
hostInitialLogTracesExpression(host, dotMetricsEnabled),
|
||||
[dotMetricsEnabled],
|
||||
hostInitialLogTracesExpression(host),
|
||||
[],
|
||||
);
|
||||
const controlListPrefix = !showFilters ? (
|
||||
<div className={styles.quickFiltersToggleContainer}>
|
||||
@@ -226,7 +219,7 @@ function Hosts(): JSX.Element {
|
||||
</div>
|
||||
<QuickFilters
|
||||
source={QuickFiltersSource.INFRA_MONITORING}
|
||||
config={getHostsQuickFiltersConfig(dotMetricsEnabled)}
|
||||
config={getHostsQuickFiltersConfig()}
|
||||
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
||||
useFieldApis={{
|
||||
metricNamespace:
|
||||
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
InframonitoringtypesHostStatusDTO,
|
||||
} from 'api/generated/services/sigNoz.schemas';
|
||||
import { K8sDetailsMetadataConfig } from 'container/InfraMonitoringK8sV2/Base/K8sBaseDetails';
|
||||
import { formatValueForExpression } from 'components/QueryBuilderV2/utils';
|
||||
import { INFRA_MONITORING_ATTR_KEYS } from 'container/InfraMonitoringK8sV2/constants';
|
||||
import { formatValueForExpression } from 'components/QueryBuilderV2/utils';
|
||||
import { SelectedItemParams } from 'container/InfraMonitoringK8sV2/hooks';
|
||||
import {
|
||||
getHostQueryPayload,
|
||||
@@ -63,7 +63,7 @@ export const hostDetailsMetadataConfig: HostDetailMetadataConfigType[] = [
|
||||
},
|
||||
{
|
||||
label: 'OPERATING SYSTEM',
|
||||
getValue: (h): string => h.meta?.['os.type'] || '-',
|
||||
getValue: (h): string => h.meta?.[INFRA_MONITORING_ATTR_KEYS.OS_TYPE] || '-',
|
||||
render: (value): React.ReactNode =>
|
||||
value !== '-' ? (
|
||||
<Badge variant="outline" className={infraHostsStyles.infraMonitoringTags}>
|
||||
@@ -101,9 +101,8 @@ export function getHostMetricsQueryPayload(
|
||||
host: InframonitoringtypesHostRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
): ReturnType<typeof getHostQueryPayload> {
|
||||
return getHostQueryPayload(host.hostName, start, end, dotMetricsEnabled);
|
||||
return getHostQueryPayload(host.hostName, start, end, true);
|
||||
}
|
||||
|
||||
export { hostWidgetInfo };
|
||||
@@ -111,17 +110,13 @@ export { hostWidgetInfo };
|
||||
export const hostGetSelectedItemExpression = (
|
||||
params: SelectedItemParams,
|
||||
): string =>
|
||||
`host.name = ${formatValueForExpression(params.selectedItem ?? '')}`;
|
||||
`${INFRA_MONITORING_ATTR_KEYS.HOST_NAME} = ${formatValueForExpression(params.selectedItem ?? '')}`;
|
||||
|
||||
export function hostInitialLogTracesExpression(
|
||||
host: InframonitoringtypesHostRecordDTO,
|
||||
dotMetricsEnabled: boolean,
|
||||
): string {
|
||||
const hostKey = dotMetricsEnabled
|
||||
? INFRA_MONITORING_ATTR_KEYS.HOST_NAME
|
||||
: 'host_name';
|
||||
const hostName = formatValueForExpression(host.hostName || '');
|
||||
return `${hostKey} = ${hostName}`;
|
||||
return `${INFRA_MONITORING_ATTR_KEYS.HOST_NAME} = ${hostName}`;
|
||||
}
|
||||
|
||||
export function hostInitialEventsExpression(
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
IQuickFiltersConfig,
|
||||
} from 'components/QuickFilters/types';
|
||||
import { TriangleAlert } from '@signozhq/icons';
|
||||
import { INFRA_MONITORING_ATTR_KEYS } from 'container/InfraMonitoringK8sV2/constants';
|
||||
import { CellValueTooltip } from 'container/InfraMonitoringK8sV2/components';
|
||||
import { INFRA_MONITORING_ATTR_KEYS } from 'container/InfraMonitoringK8sV2/constants';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
const HOSTNAME_DOCS_URL =
|
||||
@@ -62,32 +62,18 @@ export function HostnameCell({
|
||||
);
|
||||
}
|
||||
|
||||
export function getHostsQuickFiltersConfig(
|
||||
dotMetricsEnabled: boolean,
|
||||
): IQuickFiltersConfig[] {
|
||||
const hostNameKey = dotMetricsEnabled
|
||||
? INFRA_MONITORING_ATTR_KEYS.HOST_NAME
|
||||
: 'host_name';
|
||||
const osTypeKey = dotMetricsEnabled ? 'os.type' : 'os_type';
|
||||
const metricName = dotMetricsEnabled
|
||||
? 'system.cpu.load_average.15m'
|
||||
: 'system_cpu_load_average_15m';
|
||||
|
||||
const environmentKey = dotMetricsEnabled
|
||||
? 'deployment.environment'
|
||||
: 'deployment_environment';
|
||||
|
||||
export function getHostsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Host Name',
|
||||
attributeKey: {
|
||||
key: hostNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.HOST_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: metricName,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.SYSTEM_CPU_LOAD_AVERAGE_15M,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -95,12 +81,12 @@ export function getHostsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'OS Type',
|
||||
attributeKey: {
|
||||
key: osTypeKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.OS_TYPE,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: metricName,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.SYSTEM_CPU_LOAD_AVERAGE_15M,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -108,7 +94,7 @@ export function getHostsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: environmentKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
|
||||
@@ -70,7 +70,6 @@ export type GetEntityQueryPayload<T> = (
|
||||
entity: T,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
) => GetQueryResultsProps[];
|
||||
|
||||
export interface K8sDetailsTabsConfig {
|
||||
|
||||
@@ -9,33 +9,14 @@ import {
|
||||
import { SelectedItemParams } from 'container/InfraMonitoringK8sV2/hooks';
|
||||
import { INFRA_MONITORING_ATTR_KEYS } from 'container/InfraMonitoringK8sV2/constants';
|
||||
|
||||
const dotToUnder: Record<string, string> = {
|
||||
'os.type': 'os_type',
|
||||
'host.name': 'host_name',
|
||||
'deployment.environment': 'deployment_environment',
|
||||
'k8s.node.name': 'k8s_node_name',
|
||||
'k8s.cluster.name': 'k8s_cluster_name',
|
||||
'k8s.node.uid': 'k8s_node_uid',
|
||||
'k8s.cronjob.name': 'k8s_cronjob_name',
|
||||
'k8s.daemonset.name': 'k8s_daemonset_name',
|
||||
'k8s.deployment.name': 'k8s_deployment_name',
|
||||
'k8s.job.name': 'k8s_job_name',
|
||||
'k8s.namespace.name': 'k8s_namespace_name',
|
||||
'k8s.pod.name': 'k8s_pod_name',
|
||||
'k8s.pod.uid': 'k8s_pod_uid',
|
||||
'k8s.statefulset.name': 'k8s_statefulset_name',
|
||||
'k8s.persistentvolumeclaim.name': 'k8s_persistentvolumeclaim_name',
|
||||
};
|
||||
|
||||
export function getGroupedByMeta<
|
||||
T extends { meta?: Record<string, string> | null },
|
||||
>(itemData: T, groupBy: string[]): Record<string, string> {
|
||||
const result: Record<string, string> = {};
|
||||
const meta = itemData.meta ?? {};
|
||||
|
||||
groupBy.forEach((rawKey) => {
|
||||
const metaKey = (dotToUnder[rawKey] ?? rawKey) as keyof typeof meta;
|
||||
result[rawKey] = (meta[metaKey] || meta[rawKey]) ?? '';
|
||||
groupBy.forEach((key) => {
|
||||
result[key] = meta[key] ?? '';
|
||||
});
|
||||
|
||||
return result;
|
||||
@@ -47,9 +28,8 @@ export function getGroupByEl<
|
||||
const groupByValues: string[] = [];
|
||||
const meta = itemData.meta ?? {};
|
||||
|
||||
groupBy.forEach((rawKey) => {
|
||||
const metaKey = (dotToUnder[rawKey] ?? rawKey) as keyof typeof meta;
|
||||
const value = meta[metaKey] || meta[rawKey] || '<no-value>';
|
||||
groupBy.forEach((key) => {
|
||||
const value = meta[key] || '<no-value>';
|
||||
|
||||
groupByValues.push(value);
|
||||
});
|
||||
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
export const k8sClusterGetSelectedItemExpression = (
|
||||
params: SelectedItemParams,
|
||||
): string =>
|
||||
`k8s.cluster.name = ${formatValueForExpression(params.selectedItem ?? '')}`;
|
||||
`${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME} = ${formatValueForExpression(params.selectedItem ?? '')}`;
|
||||
|
||||
export const k8sClusterDetailsMetadataConfig: K8sDetailsMetadataConfig<InframonitoringtypesClusterRecordDTO>[] =
|
||||
[{ label: 'Cluster Name', getValue: (p): string => p.clusterName || '' }];
|
||||
@@ -86,7 +86,7 @@ export const k8sClusterGetEntityName = (
|
||||
export const k8sClusterGetCountsFilterExpression = (
|
||||
item: InframonitoringtypesClusterRecordDTO,
|
||||
): string =>
|
||||
`k8s.cluster.name = ${formatValueForExpression(item.clusterName ?? '')}`;
|
||||
`${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME} = ${formatValueForExpression(item.clusterName ?? '')}`;
|
||||
|
||||
export const clusterWidgetInfo = [
|
||||
{
|
||||
@@ -138,96 +138,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
cluster: InframonitoringtypesClusterRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
): GetQueryResultsProps[] => {
|
||||
const getKey = (dotKey: string, underscoreKey: string): string =>
|
||||
dotMetricsEnabled ? dotKey : underscoreKey;
|
||||
const k8sPodCpuUtilizationKey = getKey(
|
||||
'k8s.pod.cpu.usage',
|
||||
'k8s_pod_cpu_usage',
|
||||
);
|
||||
const k8sNodeAllocatableCpuKey = getKey(
|
||||
'k8s.node.allocatable_cpu',
|
||||
'k8s_node_allocatable_cpu',
|
||||
);
|
||||
const k8sPodMemoryUsageKey = getKey(
|
||||
'k8s.pod.memory.usage',
|
||||
'k8s_pod_memory_usage',
|
||||
);
|
||||
const k8sNodeAllocatableMemoryKey = getKey(
|
||||
'k8s.node.allocatable_memory',
|
||||
'k8s_node_allocatable_memory',
|
||||
);
|
||||
const k8sNodeConditionReadyKey = getKey(
|
||||
'k8s.node.condition_ready',
|
||||
'k8s_node_condition_ready',
|
||||
);
|
||||
const k8sDeploymentAvailableKey = getKey(
|
||||
'k8s.deployment.available',
|
||||
'k8s_deployment_available',
|
||||
);
|
||||
const k8sDeploymentDesiredKey = getKey(
|
||||
'k8s.deployment.desired',
|
||||
'k8s_deployment_desired',
|
||||
);
|
||||
const k8sStatefulsetCurrentPodsKey = getKey(
|
||||
'k8s.statefulset.current_pods',
|
||||
'k8s_statefulset_current_pods',
|
||||
);
|
||||
const k8sStatefulsetDesiredPodsKey = getKey(
|
||||
'k8s.statefulset.desired_pods',
|
||||
'k8s_statefulset_desired_pods',
|
||||
);
|
||||
const k8sStatefulsetReadyPodsKey = getKey(
|
||||
'k8s.statefulset.ready_pods',
|
||||
'k8s_statefulset_ready_pods',
|
||||
);
|
||||
const k8sStatefulsetUpdatedPodsKey = getKey(
|
||||
'k8s.statefulset.updated_pods',
|
||||
'k8s_statefulset_updated_pods',
|
||||
);
|
||||
const k8sDaemonsetCurrentScheduledNodesKey = getKey(
|
||||
'k8s.daemonset.current_scheduled_nodes',
|
||||
'k8s_daemonset_current_scheduled_nodes',
|
||||
);
|
||||
const k8sDaemonsetDesiredScheduledNodesKey = getKey(
|
||||
'k8s.daemonset.desired_scheduled_nodes',
|
||||
'k8s_daemonset_desired_scheduled_nodes',
|
||||
);
|
||||
const k8sDaemonsetReadyNodesKey = getKey(
|
||||
'k8s.daemonset.ready_nodes',
|
||||
'k8s_daemonset_ready_nodes',
|
||||
);
|
||||
const k8sJobActivePodsKey = getKey(
|
||||
'k8s.job.active_pods',
|
||||
'k8s_job_active_pods',
|
||||
);
|
||||
const k8sJobSuccessfulPodsKey = getKey(
|
||||
'k8s.job.successful_pods',
|
||||
'k8s_job_successful_pods',
|
||||
);
|
||||
const k8sJobFailedPodsKey = getKey(
|
||||
'k8s.job.failed_pods',
|
||||
'k8s_job_failed_pods',
|
||||
);
|
||||
const k8sJobDesiredSuccessfulPodsKey = getKey(
|
||||
'k8s.job.desired_successful_pods',
|
||||
'k8s_job_desired_successful_pods',
|
||||
);
|
||||
const k8sClusterNameKey = getKey('k8s.cluster.name', 'k8s_cluster_name');
|
||||
const k8sNodeNameKey = getKey('k8s.node.name', 'k8s_node_name');
|
||||
const k8sDeploymentNameKey = getKey(
|
||||
'k8s.deployment.name',
|
||||
'k8s_deployment_name',
|
||||
);
|
||||
const k8sNamespaceNameKey = getKey('k8s.namespace.name', 'k8s_namespace_name');
|
||||
const k8sStatefulsetNameKey = getKey(
|
||||
'k8s.statefulset.name',
|
||||
'k8s_statefulset_name',
|
||||
);
|
||||
const k8sDaemonsetNameKey = getKey('k8s.daemonset.name', 'k8s_daemonset_name');
|
||||
const k8sJobNameKey = getKey('k8s.job.name', 'k8s_job_name');
|
||||
|
||||
return [
|
||||
{
|
||||
selectedTime: 'GLOBAL_TIME',
|
||||
@@ -239,7 +150,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_cpu_usage--float64--Gauge--true',
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -253,7 +164,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -278,7 +189,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_cpu_usage--float64--Gauge--true',
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'min',
|
||||
@@ -292,7 +203,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -317,7 +228,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_cpu_usage--float64--Gauge--true',
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -331,7 +242,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -356,7 +267,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_allocatable_cpu--float64--Gauge--true',
|
||||
key: k8sNodeAllocatableCpuKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_ALLOCATABLE_CPU,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -370,7 +281,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -429,7 +340,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_memory_usage--float64--Gauge--true',
|
||||
key: k8sPodMemoryUsageKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -443,7 +354,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -468,7 +379,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_memory_usage--float64--Gauge--true',
|
||||
key: k8sPodMemoryUsageKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'min',
|
||||
@@ -482,7 +393,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -507,7 +418,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_memory_usage--float64--Gauge--true',
|
||||
key: k8sPodMemoryUsageKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -521,7 +432,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -546,7 +457,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_allocatable_memory--float64--Gauge--true',
|
||||
key: k8sNodeAllocatableMemoryKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_ALLOCATABLE_MEMORY,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -560,7 +471,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -619,7 +530,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_condition_ready--float64--Gauge--true',
|
||||
key: k8sNodeConditionReadyKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CONDITION_READY,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -633,7 +544,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -647,18 +558,18 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
having: [
|
||||
{
|
||||
columnName: `MAX(${k8sNodeConditionReadyKey})`,
|
||||
columnName: `MAX(${INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CONDITION_READY})`,
|
||||
op: '=',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
legend: `{{${k8sNodeNameKey}}}`,
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME}}}`,
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
@@ -705,7 +616,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_condition_ready--float64--Gauge--true',
|
||||
key: k8sNodeConditionReadyKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CONDITION_READY,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -719,7 +630,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -733,18 +644,18 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
having: [
|
||||
{
|
||||
columnName: `MAX(${k8sNodeConditionReadyKey})`,
|
||||
columnName: `MAX(${INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CONDITION_READY})`,
|
||||
op: '=',
|
||||
value: 0,
|
||||
},
|
||||
],
|
||||
legend: `{{${k8sNodeNameKey}}}`,
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME}}}`,
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
@@ -791,7 +702,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_deployment_available--float64--Gauge--true',
|
||||
key: k8sDeploymentAvailableKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_AVAILABLE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -805,7 +716,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -819,13 +730,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_deployment_name--string--tag--false',
|
||||
key: k8sDeploymentNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -843,7 +754,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_deployment_desired--float64--Gauge--true',
|
||||
key: k8sDeploymentDesiredKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_DESIRED,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -857,7 +768,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -871,13 +782,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_deployment_name--string--tag--false',
|
||||
key: k8sDeploymentNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -941,7 +852,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_statefulset_current_pods--float64--Gauge--true',
|
||||
key: k8sStatefulsetCurrentPodsKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_CURRENT_PODS,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -955,7 +866,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -969,13 +880,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_statefulset_name--string--tag--false',
|
||||
key: k8sStatefulsetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -993,7 +904,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_statefulset_desired_pods--float64--Gauge--true',
|
||||
key: k8sStatefulsetDesiredPodsKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_DESIRED_PODS,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -1007,7 +918,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1021,13 +932,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_statefulset_name--string--tag--false',
|
||||
key: k8sStatefulsetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1045,7 +956,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_statefulset_ready_pods--float64--Gauge--true',
|
||||
key: k8sStatefulsetReadyPodsKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_READY_PODS,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -1059,7 +970,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1073,13 +984,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_statefulset_name--string--tag--false',
|
||||
key: k8sStatefulsetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1097,7 +1008,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_statefulset_updated_pods--float64--Gauge--true',
|
||||
key: k8sStatefulsetUpdatedPodsKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_UPDATED_PODS,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -1111,7 +1022,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1125,13 +1036,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_statefulset_name--string--tag--false',
|
||||
key: k8sStatefulsetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1219,7 +1130,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_daemonset_current_scheduled_nodes--float64--Gauge--true',
|
||||
key: k8sDaemonsetCurrentScheduledNodesKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_CURRENT_SCHEDULED_NODES,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1233,7 +1144,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1247,7 +1158,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_daemonset_name--string--tag--false',
|
||||
key: k8sDaemonsetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1265,7 +1176,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_daemonset_desired_scheduled_nodes--float64--Gauge--true',
|
||||
key: k8sDaemonsetDesiredScheduledNodesKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_DESIRED_SCHEDULED_NODES,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1279,7 +1190,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1293,7 +1204,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_daemonset_name--string--tag--false',
|
||||
key: k8sDaemonsetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1311,7 +1222,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_daemonset_ready_nodes--float64--Gauge--true',
|
||||
key: k8sDaemonsetReadyNodesKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_READY_NODES,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1325,7 +1236,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1339,7 +1250,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_daemonset_name--string--tag--false',
|
||||
key: k8sDaemonsetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1415,7 +1326,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_job_active_pods--float64--Gauge--true',
|
||||
key: k8sJobActivePodsKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_ACTIVE_PODS,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -1429,7 +1340,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1443,13 +1354,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_job_name--string--tag--false',
|
||||
key: k8sJobNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1467,7 +1378,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_job_successful_pods--float64--Gauge--true',
|
||||
key: k8sJobSuccessfulPodsKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_SUCCESSFUL_PODS,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -1481,7 +1392,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1495,13 +1406,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_job_name--string--tag--false',
|
||||
key: k8sJobNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1519,7 +1430,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_job_failed_pods--float64--Gauge--true',
|
||||
key: k8sJobFailedPodsKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_FAILED_PODS,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -1533,7 +1444,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1547,13 +1458,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_job_name--string--tag--false',
|
||||
key: k8sJobNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1571,7 +1482,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_job_desired_successful_pods--float64--Gauge--true',
|
||||
key: k8sJobDesiredSuccessfulPodsKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_DESIRED_SUCCESSFUL_PODS,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -1585,7 +1496,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1599,13 +1510,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_job_name--string--tag--false',
|
||||
key: k8sJobNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
|
||||
@@ -100,54 +100,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
daemonSet: InframonitoringtypesDaemonSetRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
): GetQueryResultsProps[] => {
|
||||
const k8sPodCpuUtilizationKey = dotMetricsEnabled
|
||||
? 'k8s.pod.cpu.usage'
|
||||
: 'k8s_pod_cpu_usage';
|
||||
|
||||
const k8sContainerCpuRequestKey = dotMetricsEnabled
|
||||
? 'k8s.container.cpu_request'
|
||||
: 'k8s_container_cpu_request';
|
||||
|
||||
const k8sContainerCpuLimitKey = dotMetricsEnabled
|
||||
? 'k8s.container.cpu_limit'
|
||||
: 'k8s_container_cpu_limit';
|
||||
|
||||
const k8sPodMemoryUsageKey = dotMetricsEnabled
|
||||
? 'k8s.pod.memory.usage'
|
||||
: 'k8s_pod_memory_usage';
|
||||
|
||||
const k8sContainerMemoryRequestKey = dotMetricsEnabled
|
||||
? 'k8s.container.memory_request'
|
||||
: 'k8s_container_memory_request';
|
||||
|
||||
const k8sContainerMemoryLimitKey = dotMetricsEnabled
|
||||
? 'k8s.container.memory_limit'
|
||||
: 'k8s_container_memory_limit';
|
||||
|
||||
const k8sPodNetworkIoKey = dotMetricsEnabled
|
||||
? 'k8s.pod.network.io'
|
||||
: 'k8s_pod_network_io';
|
||||
|
||||
const k8sPodNetworkErrorsKey = dotMetricsEnabled
|
||||
? 'k8s.pod.network.errors'
|
||||
: 'k8s_pod_network_errors';
|
||||
|
||||
const k8sDaemonSetNameKey = dotMetricsEnabled
|
||||
? 'k8s.daemonset.name'
|
||||
: 'k8s_daemonset_name';
|
||||
|
||||
const k8sPodNameKey = dotMetricsEnabled ? 'k8s.pod.name' : 'k8s_pod_name';
|
||||
|
||||
const k8sNamespaceNameKey = dotMetricsEnabled
|
||||
? 'k8s.namespace.name'
|
||||
: 'k8s_namespace_name';
|
||||
|
||||
const k8sClusterNameKey = dotMetricsEnabled
|
||||
? 'k8s.cluster.name'
|
||||
: 'k8s_cluster_name';
|
||||
|
||||
const clusterName =
|
||||
daemonSet.meta?.[INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME] ?? '';
|
||||
const namespaceName =
|
||||
@@ -159,7 +112,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -170,7 +123,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -189,7 +142,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_cpu_usage--float64--Gauge--true',
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -203,7 +156,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_daemonset_name--string--tag--false',
|
||||
key: k8sDaemonSetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -231,7 +184,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_cpu_request--float64--Gauge--true',
|
||||
key: k8sContainerCpuRequestKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_REQUEST,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -245,7 +198,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: k8sPodNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -273,7 +226,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_cpu_limit--float64--Gauge--true',
|
||||
key: k8sContainerCpuLimitKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_LIMIT,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -287,7 +240,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: k8sPodNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -349,7 +302,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_memory_usage--float64--Gauge--true',
|
||||
key: k8sPodMemoryUsageKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -363,7 +316,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_daemonset_name--string--tag--false',
|
||||
key: k8sDaemonSetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -391,7 +344,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_memory_request--float64--Gauge--true',
|
||||
key: k8sContainerMemoryRequestKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_REQUEST,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -405,7 +358,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: k8sPodNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -433,7 +386,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_memory_limit--float64--Gauge--true',
|
||||
key: k8sContainerMemoryLimitKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_LIMIT,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -447,7 +400,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: k8sPodNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -509,7 +462,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_network_io--float64--Sum--true',
|
||||
key: k8sPodNetworkIoKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_IO,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'rate',
|
||||
@@ -523,7 +476,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_daemonset_name--string--tag--false',
|
||||
key: k8sDaemonSetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -598,7 +551,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_network_errors--float64--Sum--true',
|
||||
key: k8sPodNetworkErrorsKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_ERRORS,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'increase',
|
||||
@@ -612,7 +565,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_daemonset_name--string--tag--false',
|
||||
key: k8sDaemonSetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -684,15 +637,10 @@ export const getDaemonSetPodMetricsQueryPayload = (
|
||||
daemonSet: InframonitoringtypesDaemonSetRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
): GetQueryResultsProps[] => {
|
||||
const k8sDaemonSetNameKey = dotMetricsEnabled
|
||||
? 'k8s.daemonset.name'
|
||||
: 'k8s_daemonset_name';
|
||||
|
||||
return getPodUtilizationByPodQueryPayloads(
|
||||
{
|
||||
workloadNameKey: k8sDaemonSetNameKey,
|
||||
workloadNameKey: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
workloadNameValue:
|
||||
daemonSet.meta?.[INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME] ?? '',
|
||||
clusterName:
|
||||
@@ -702,6 +650,5 @@ export const getDaemonSetPodMetricsQueryPayload = (
|
||||
},
|
||||
start,
|
||||
end,
|
||||
dotMetricsEnabled,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -100,52 +100,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
deployment: InframonitoringtypesDeploymentRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
): GetQueryResultsProps[] => {
|
||||
const k8sPodCpuUtilizationKey = dotMetricsEnabled
|
||||
? 'k8s.pod.cpu.usage'
|
||||
: 'k8s_pod_cpu_usage';
|
||||
|
||||
const k8sContainerCpuRequestKey = dotMetricsEnabled
|
||||
? 'k8s.container.cpu_request'
|
||||
: 'k8s_container_cpu_request';
|
||||
|
||||
const k8sContainerCpuLimitKey = dotMetricsEnabled
|
||||
? 'k8s.container.cpu_limit'
|
||||
: 'k8s_container_cpu_limit';
|
||||
|
||||
const k8sPodMemoryUsageKey = dotMetricsEnabled
|
||||
? 'k8s.pod.memory.usage'
|
||||
: 'k8s_pod_memory_usage';
|
||||
|
||||
const k8sContainerMemoryRequestKey = dotMetricsEnabled
|
||||
? 'k8s.container.memory_request'
|
||||
: 'k8s_container_memory_request';
|
||||
|
||||
const k8sContainerMemoryLimitKey = dotMetricsEnabled
|
||||
? 'k8s.container.memory_limit'
|
||||
: 'k8s_container_memory_limit';
|
||||
|
||||
const k8sPodNetworkIoKey = dotMetricsEnabled
|
||||
? 'k8s.pod.network.io'
|
||||
: 'k8s_pod_network_io';
|
||||
|
||||
const k8sPodNetworkErrorsKey = dotMetricsEnabled
|
||||
? 'k8s.pod.network.errors'
|
||||
: 'k8s_pod_network_errors';
|
||||
|
||||
const k8sDeploymentNameKey = dotMetricsEnabled
|
||||
? 'k8s.deployment.name'
|
||||
: 'k8s_deployment_name';
|
||||
|
||||
const k8sPodNameKey = dotMetricsEnabled ? 'k8s.pod.name' : 'k8s_pod_name';
|
||||
const k8sClusterNameKey = dotMetricsEnabled
|
||||
? 'k8s.cluster.name'
|
||||
: 'k8s_cluster_name';
|
||||
const k8sNamespaceNameKey = dotMetricsEnabled
|
||||
? 'k8s.namespace.name'
|
||||
: 'k8s_namespace_name';
|
||||
|
||||
const clusterName =
|
||||
deployment.meta?.[INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME] ?? '';
|
||||
|
||||
@@ -158,7 +113,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -169,7 +124,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -188,7 +143,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_cpu_usage--float64--Gauge--true',
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -202,7 +157,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_deployment_name--string--tag--false',
|
||||
key: k8sDeploymentNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -230,7 +185,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_cpu_request--float64--Gauge--true',
|
||||
key: k8sContainerCpuRequestKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_REQUEST,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -244,7 +199,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: k8sPodNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -272,7 +227,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_cpu_limit--float64--Gauge--true',
|
||||
key: k8sContainerCpuLimitKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_LIMIT,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -286,7 +241,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: k8sPodNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -348,7 +303,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_memory_usage--float64--Gauge--true',
|
||||
key: k8sPodMemoryUsageKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -362,7 +317,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_deployment_name--string--tag--false',
|
||||
key: k8sDeploymentNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -390,7 +345,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_memory_request--float64--Gauge--true',
|
||||
key: k8sContainerMemoryRequestKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_REQUEST,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -404,7 +359,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: k8sPodNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -432,7 +387,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_memory_limit--float64--Gauge--true',
|
||||
key: k8sContainerMemoryLimitKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_LIMIT,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -446,7 +401,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: k8sPodNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -508,7 +463,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_network_io--float64--Sum--true',
|
||||
key: k8sPodNetworkIoKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_IO,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'rate',
|
||||
@@ -522,7 +477,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_deployment_name--string--tag--false',
|
||||
key: k8sDeploymentNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -597,7 +552,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_network_errors--float64--Sum--true',
|
||||
key: k8sPodNetworkErrorsKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_ERRORS,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'increase',
|
||||
@@ -611,7 +566,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_deployment_name--string--tag--false',
|
||||
key: k8sDeploymentNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -683,15 +638,10 @@ export const getDeploymentPodMetricsQueryPayload = (
|
||||
deployment: InframonitoringtypesDeploymentRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
): GetQueryResultsProps[] => {
|
||||
const k8sDeploymentNameKey = dotMetricsEnabled
|
||||
? 'k8s.deployment.name'
|
||||
: 'k8s_deployment_name';
|
||||
|
||||
return getPodUtilizationByPodQueryPayloads(
|
||||
): GetQueryResultsProps[] =>
|
||||
getPodUtilizationByPodQueryPayloads(
|
||||
{
|
||||
workloadNameKey: k8sDeploymentNameKey,
|
||||
workloadNameKey: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
workloadNameValue:
|
||||
deployment.meta?.[INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME] ?? '',
|
||||
clusterName:
|
||||
@@ -701,6 +651,4 @@ export const getDeploymentPodMetricsQueryPayload = (
|
||||
},
|
||||
start,
|
||||
end,
|
||||
dotMetricsEnabled,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -40,7 +40,6 @@ interface EntityMetricsProps<T> {
|
||||
node: T,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
) => GetQueryResultsProps[];
|
||||
queryKey: string;
|
||||
category: InfraMonitoringEntity;
|
||||
|
||||
@@ -85,7 +85,6 @@ describe('EntityMetrics time range wiring', () => {
|
||||
entity,
|
||||
START_SECONDS,
|
||||
END_SECONDS,
|
||||
false,
|
||||
);
|
||||
expect(mockBuildChartConfig).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
|
||||
@@ -13,8 +13,6 @@ import { SuccessResponse } from 'types/api';
|
||||
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
||||
import uPlot from 'uplot';
|
||||
|
||||
import { FeatureKeys } from 'constants/features';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
import { getMetricsTableData, MetricsTableData } from './utils';
|
||||
|
||||
export interface UseEntityMetricsParams<T> {
|
||||
@@ -25,7 +23,6 @@ export interface UseEntityMetricsParams<T> {
|
||||
entity: T,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
) => GetQueryResultsProps[];
|
||||
visibilities: boolean[];
|
||||
category: InfraMonitoringEntity;
|
||||
@@ -46,26 +43,9 @@ export function useEntityMetrics<T>({
|
||||
visibilities,
|
||||
category,
|
||||
}: UseEntityMetricsParams<T>): UseEntityMetricsResult {
|
||||
const { featureFlags } = useAppContext();
|
||||
const dotMetricsEnabled =
|
||||
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||
?.active || false;
|
||||
|
||||
const queryPayloads = useMemo(
|
||||
() =>
|
||||
getEntityQueryPayload(
|
||||
entity,
|
||||
timeRange.startTime,
|
||||
timeRange.endTime,
|
||||
dotMetricsEnabled,
|
||||
),
|
||||
[
|
||||
getEntityQueryPayload,
|
||||
entity,
|
||||
timeRange.startTime,
|
||||
timeRange.endTime,
|
||||
dotMetricsEnabled,
|
||||
],
|
||||
() => getEntityQueryPayload(entity, timeRange.startTime, timeRange.endTime),
|
||||
[getEntityQueryPayload, entity, timeRange.startTime, timeRange.endTime],
|
||||
);
|
||||
|
||||
const queries = useQueries(
|
||||
|
||||
@@ -30,7 +30,6 @@ interface CreatePodMetricsTabParams<T> {
|
||||
entity: T,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
) => GetQueryResultsProps[];
|
||||
queryKey: string;
|
||||
category: InfraMonitoringEntity;
|
||||
|
||||
@@ -26,8 +26,6 @@ import {
|
||||
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import { FeatureKeys } from '../../constants/features';
|
||||
import { useAppContext } from '../../providers/App/App';
|
||||
import { K8sDynamicList } from './Base/K8sDynamicList';
|
||||
import {
|
||||
GetClustersQuickFiltersConfig,
|
||||
@@ -128,69 +126,64 @@ export default function InfraMonitoringK8s(): JSX.Element {
|
||||
setShowFilters((show) => !show);
|
||||
}, []);
|
||||
|
||||
const { featureFlags } = useAppContext();
|
||||
const dotMetricsEnabled =
|
||||
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||
?.active || false;
|
||||
|
||||
const categories = useMemo(
|
||||
() => [
|
||||
{
|
||||
key: K8sCategories.PODS,
|
||||
label: 'Pods',
|
||||
icon: <Container size={14} />,
|
||||
config: GetPodsQuickFiltersConfig(dotMetricsEnabled),
|
||||
config: GetPodsQuickFiltersConfig(),
|
||||
},
|
||||
{
|
||||
key: K8sCategories.NODES,
|
||||
label: 'Nodes',
|
||||
icon: <Workflow size={14} />,
|
||||
config: GetNodesQuickFiltersConfig(dotMetricsEnabled),
|
||||
config: GetNodesQuickFiltersConfig(),
|
||||
},
|
||||
{
|
||||
key: K8sCategories.NAMESPACES,
|
||||
label: 'Namespaces',
|
||||
icon: <FilePenLine size={14} />,
|
||||
config: GetNamespaceQuickFiltersConfig(dotMetricsEnabled),
|
||||
config: GetNamespaceQuickFiltersConfig(),
|
||||
},
|
||||
{
|
||||
key: K8sCategories.CLUSTERS,
|
||||
label: 'Clusters',
|
||||
icon: <Boxes size={14} />,
|
||||
config: GetClustersQuickFiltersConfig(dotMetricsEnabled),
|
||||
config: GetClustersQuickFiltersConfig(),
|
||||
},
|
||||
{
|
||||
key: K8sCategories.DEPLOYMENTS,
|
||||
label: 'Deployments',
|
||||
icon: <Computer size={14} />,
|
||||
config: GetDeploymentsQuickFiltersConfig(dotMetricsEnabled),
|
||||
config: GetDeploymentsQuickFiltersConfig(),
|
||||
},
|
||||
{
|
||||
key: K8sCategories.JOBS,
|
||||
label: 'Jobs',
|
||||
icon: <Bolt size={14} />,
|
||||
config: GetJobsQuickFiltersConfig(dotMetricsEnabled),
|
||||
config: GetJobsQuickFiltersConfig(),
|
||||
},
|
||||
{
|
||||
key: K8sCategories.DAEMONSETS,
|
||||
label: 'DaemonSets',
|
||||
icon: <Group size={14} />,
|
||||
config: GetDaemonsetsQuickFiltersConfig(dotMetricsEnabled),
|
||||
config: GetDaemonsetsQuickFiltersConfig(),
|
||||
},
|
||||
{
|
||||
key: K8sCategories.STATEFULSETS,
|
||||
label: 'StatefulSets',
|
||||
icon: <ArrowUpDown size={14} />,
|
||||
config: GetStatefulsetsQuickFiltersConfig(dotMetricsEnabled),
|
||||
config: GetStatefulsetsQuickFiltersConfig(),
|
||||
},
|
||||
{
|
||||
key: K8sCategories.VOLUMES,
|
||||
label: 'Volumes',
|
||||
icon: <HardDrive size={14} />,
|
||||
config: GetVolumesQuickFiltersConfig(dotMetricsEnabled),
|
||||
config: GetVolumesQuickFiltersConfig(),
|
||||
},
|
||||
],
|
||||
[dotMetricsEnabled],
|
||||
[],
|
||||
);
|
||||
|
||||
const selectedCategoryConfig = useMemo(
|
||||
|
||||
@@ -96,28 +96,7 @@ export const getJobMetricsQueryPayload = (
|
||||
job: InframonitoringtypesJobRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
): GetQueryResultsProps[] => {
|
||||
const k8sPodCpuUtilizationKey = dotMetricsEnabled
|
||||
? 'k8s.pod.cpu.usage'
|
||||
: 'k8s_pod_cpu_usage';
|
||||
const k8sPodMemoryUsageKey = dotMetricsEnabled
|
||||
? 'k8s.pod.memory.usage'
|
||||
: 'k8s_pod_memory_usage';
|
||||
const k8sPodNetworkIoKey = dotMetricsEnabled
|
||||
? 'k8s.pod.network.io'
|
||||
: 'k8s_pod_network_io';
|
||||
const k8sPodNetworkErrorsKey = dotMetricsEnabled
|
||||
? 'k8s.pod.network.errors'
|
||||
: 'k8s_pod_network_errors';
|
||||
const k8sJobNameKey = dotMetricsEnabled ? 'k8s.job.name' : 'k8s_job_name';
|
||||
const k8sClusterNameKey = dotMetricsEnabled
|
||||
? 'k8s.cluster.name'
|
||||
: 'k8s_cluster_name';
|
||||
const k8sNamespaceNameKey = dotMetricsEnabled
|
||||
? 'k8s.namespace.name'
|
||||
: 'k8s_namespace_name';
|
||||
|
||||
const clusterName =
|
||||
job.meta?.[INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME] ?? '';
|
||||
const namespaceName =
|
||||
@@ -129,7 +108,7 @@ export const getJobMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_job_name--string--tag--false',
|
||||
key: k8sJobNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -140,7 +119,7 @@ export const getJobMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -151,7 +130,7 @@ export const getJobMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -170,7 +149,7 @@ export const getJobMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_cpu_usage--float64--Gauge--true',
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -231,7 +210,7 @@ export const getJobMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_memory_usage--float64--Gauge--true',
|
||||
key: k8sPodMemoryUsageKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -292,7 +271,7 @@ export const getJobMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_network_io--float64--Sum--true',
|
||||
key: k8sPodNetworkIoKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_IO,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'rate',
|
||||
@@ -366,7 +345,7 @@ export const getJobMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_network_errors--float64--Sum--true',
|
||||
key: k8sPodNetworkErrorsKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_ERRORS,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'increase',
|
||||
@@ -437,13 +416,10 @@ export const getJobPodMetricsQueryPayload = (
|
||||
job: InframonitoringtypesJobRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
): GetQueryResultsProps[] => {
|
||||
const k8sJobNameKey = dotMetricsEnabled ? 'k8s.job.name' : 'k8s_job_name';
|
||||
|
||||
return getPodUtilizationByPodQueryPayloads(
|
||||
): GetQueryResultsProps[] =>
|
||||
getPodUtilizationByPodQueryPayloads(
|
||||
{
|
||||
workloadNameKey: k8sJobNameKey,
|
||||
workloadNameKey: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME,
|
||||
workloadNameValue: job.jobName ?? '',
|
||||
clusterName: job.meta?.[INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME] ?? '',
|
||||
namespaceName:
|
||||
@@ -451,6 +427,4 @@ export const getJobPodMetricsQueryPayload = (
|
||||
},
|
||||
start,
|
||||
end,
|
||||
dotMetricsEnabled,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -166,97 +166,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
namespace: InframonitoringtypesNamespaceRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
): GetQueryResultsProps[] => {
|
||||
const getKey = (dotKey: string, underscoreKey: string): string =>
|
||||
dotMetricsEnabled ? dotKey : underscoreKey;
|
||||
const k8sPodCpuUtilizationKey = getKey(
|
||||
'k8s.pod.cpu.usage',
|
||||
'k8s_pod_cpu_usage',
|
||||
);
|
||||
const k8sContainerCpuRequestKey = getKey(
|
||||
'k8s.container.cpu_request',
|
||||
'k8s_container_cpu_request',
|
||||
);
|
||||
const k8sPodMemoryUsageKey = getKey(
|
||||
'k8s.pod.memory.usage',
|
||||
'k8s_pod_memory_usage',
|
||||
);
|
||||
const k8sContainerMemoryRequestKey = getKey(
|
||||
'k8s.container.memory_request',
|
||||
'k8s_container_memory_request',
|
||||
);
|
||||
const k8sPodMemoryWorkingSetKey = getKey(
|
||||
'k8s.pod.memory.working_set',
|
||||
'k8s_pod_memory_working_set',
|
||||
);
|
||||
const k8sPodMemoryRssKey = getKey('k8s.pod.memory.rss', 'k8s_pod_memory_rss');
|
||||
const k8sPodNetworkIoKey = getKey('k8s.pod.network.io', 'k8s_pod_network_io');
|
||||
const k8sPodNetworkErrorsKey = getKey(
|
||||
'k8s.pod.network.errors',
|
||||
'k8s_pod_network_errors',
|
||||
);
|
||||
const k8sStatefulsetCurrentPodsKey = getKey(
|
||||
'k8s.statefulset.current_pods',
|
||||
'k8s_statefulset_current_pods',
|
||||
);
|
||||
const k8sStatefulsetDesiredPodsKey = getKey(
|
||||
'k8s.statefulset.desired_pods',
|
||||
'k8s_statefulset_desired_pods',
|
||||
);
|
||||
const k8sStatefulsetUpdatedPodsKey = getKey(
|
||||
'k8s.statefulset.updated_pods',
|
||||
'k8s_statefulset_updated_pods',
|
||||
);
|
||||
const k8sReplicasetDesiredKey = getKey(
|
||||
'k8s.replicaset.desired',
|
||||
'k8s_replicaset_desired',
|
||||
);
|
||||
const k8sReplicasetAvailableKey = getKey(
|
||||
'k8s.replicaset.available',
|
||||
'k8s_replicaset_available',
|
||||
);
|
||||
const k8sDaemonsetDesiredScheduledNodesKey = getKey(
|
||||
'k8s.daemonset.desired_scheduled_nodes',
|
||||
'k8s_daemonset_desired_scheduled_nodes',
|
||||
);
|
||||
const k8sDaemonsetCurrentScheduledNodesKey = getKey(
|
||||
'k8s.daemonset.current_scheduled_nodes',
|
||||
'k8s_daemonset_current_scheduled_nodes',
|
||||
);
|
||||
const k8sDaemonsetReadyNodesKey = getKey(
|
||||
'k8s.daemonset.ready_nodes',
|
||||
'k8s_daemonset_ready_nodes',
|
||||
);
|
||||
const k8sDaemonsetMisscheduledNodesKey = getKey(
|
||||
'k8s.daemonset.misscheduled_nodes',
|
||||
'k8s_daemonset_misscheduled_nodes',
|
||||
);
|
||||
const k8sDeploymentDesiredKey = getKey(
|
||||
'k8s.deployment.desired',
|
||||
'k8s_deployment_desired',
|
||||
);
|
||||
const k8sDeploymentAvailableKey = getKey(
|
||||
'k8s.deployment.available',
|
||||
'k8s_deployment_available',
|
||||
);
|
||||
const k8sNamespaceNameKey = getKey('k8s.namespace.name', 'k8s_namespace_name');
|
||||
const k8sPodNameKey = getKey('k8s.pod.name', 'k8s_pod_name');
|
||||
const k8sStatefulsetNameKey = getKey(
|
||||
'k8s.statefulset.name',
|
||||
'k8s_statefulset_name',
|
||||
);
|
||||
const k8sReplicasetNameKey = getKey(
|
||||
'k8s.replicaset.name',
|
||||
'k8s_replicaset_name',
|
||||
);
|
||||
const k8sDaemonsetNameKey = getKey('k8s.daemonset.name', 'k8s_daemonset_name');
|
||||
const k8sDeploymentNameKey = getKey(
|
||||
'k8s.deployment.name',
|
||||
'k8s_deployment_name',
|
||||
);
|
||||
const k8sClusterNameKey = getKey('k8s.cluster.name', 'k8s_cluster_name');
|
||||
|
||||
const clusterName =
|
||||
namespace.meta?.[INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME] ?? '';
|
||||
|
||||
@@ -266,7 +176,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -284,8 +194,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sPodCpuUtilizationKey,
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -298,8 +208,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '47b3adae',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -324,8 +234,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sContainerCpuRequestKey,
|
||||
key: k8sContainerCpuRequestKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_REQUEST,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_REQUEST,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -338,8 +248,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '93d2be5e',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -364,8 +274,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sPodCpuUtilizationKey,
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'min',
|
||||
@@ -378,8 +288,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '795eb679',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -404,8 +314,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sPodCpuUtilizationKey,
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -418,8 +328,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '6792adbe',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -478,8 +388,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sPodMemoryUsageKey,
|
||||
key: k8sPodMemoryUsageKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -492,8 +402,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '10011298',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -518,8 +428,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sContainerMemoryRequestKey,
|
||||
key: k8sContainerMemoryRequestKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_REQUEST,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_REQUEST,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -532,8 +442,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: 'ea53b656',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -558,8 +468,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sPodMemoryWorkingSetKey,
|
||||
key: k8sPodMemoryWorkingSetKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_WORKING_SET,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_WORKING_SET,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -572,8 +482,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '674ace83',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -598,8 +508,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sPodMemoryRssKey,
|
||||
key: k8sPodMemoryRssKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_RSS,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_RSS,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -612,8 +522,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '187dbdb3',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -638,8 +548,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sPodMemoryUsageKey,
|
||||
key: k8sPodMemoryUsageKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'min',
|
||||
@@ -652,8 +562,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: 'a3dbf468',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -678,8 +588,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sPodMemoryUsageKey,
|
||||
key: k8sPodMemoryUsageKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -692,8 +602,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '4b2406c2',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -752,8 +662,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sPodCpuUtilizationKey,
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -766,8 +676,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: 'c3a73f0a',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -781,13 +691,13 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: k8sPodNameKey,
|
||||
key: k8sPodNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
having: [],
|
||||
legend: `{{${k8sPodNameKey}}}`,
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}}}`,
|
||||
limit: 10,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
@@ -833,8 +743,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sPodMemoryUsageKey,
|
||||
key: k8sPodMemoryUsageKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -847,8 +757,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '5cad3379',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -862,13 +772,13 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: k8sPodNameKey,
|
||||
key: k8sPodNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
having: [],
|
||||
legend: `{{${k8sPodNameKey}}}`,
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}}}`,
|
||||
limit: 10,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
@@ -914,8 +824,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sPodNetworkIoKey,
|
||||
key: k8sPodNetworkIoKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_IO,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_IO,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'rate',
|
||||
@@ -928,8 +838,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '00f5c5e1',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1001,8 +911,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sPodNetworkErrorsKey,
|
||||
key: k8sPodNetworkErrorsKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_ERRORS,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_ERRORS,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'increase',
|
||||
@@ -1015,8 +925,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '3aa8e064',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1088,8 +998,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sStatefulsetCurrentPodsKey,
|
||||
key: k8sStatefulsetCurrentPodsKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_CURRENT_PODS,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_CURRENT_PODS,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1102,8 +1012,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '5f2a55c5',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1117,8 +1027,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: k8sStatefulsetNameKey,
|
||||
key: k8sStatefulsetNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1135,8 +1045,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sStatefulsetDesiredPodsKey,
|
||||
key: k8sStatefulsetDesiredPodsKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_DESIRED_PODS,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_DESIRED_PODS,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1149,8 +1059,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '13bd7a1d',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1164,8 +1074,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: k8sStatefulsetNameKey,
|
||||
key: k8sStatefulsetNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1182,8 +1092,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sStatefulsetUpdatedPodsKey,
|
||||
key: k8sStatefulsetUpdatedPodsKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_UPDATED_PODS,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_UPDATED_PODS,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1196,8 +1106,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '9d287c73',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1211,8 +1121,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: k8sStatefulsetNameKey,
|
||||
key: k8sStatefulsetNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1263,8 +1173,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sReplicasetDesiredKey,
|
||||
key: k8sReplicasetDesiredKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_DESIRED,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_DESIRED,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1277,8 +1187,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '0c1e655c',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1292,14 +1202,14 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: k8sReplicasetNameKey,
|
||||
key: k8sReplicasetNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
having: [
|
||||
{
|
||||
columnName: `MAX(${k8sReplicasetDesiredKey})`,
|
||||
columnName: `MAX(${INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_DESIRED})`,
|
||||
op: '>',
|
||||
value: 0,
|
||||
},
|
||||
@@ -1316,8 +1226,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sReplicasetAvailableKey,
|
||||
key: k8sReplicasetAvailableKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_AVAILABLE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_AVAILABLE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1330,8 +1240,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: 'b2296bdb',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1345,14 +1255,14 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: k8sReplicasetNameKey,
|
||||
key: k8sReplicasetNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
having: [
|
||||
{
|
||||
columnName: `MAX(${k8sReplicasetDesiredKey})`,
|
||||
columnName: `MAX(${INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_DESIRED})`,
|
||||
op: '>',
|
||||
value: 0,
|
||||
},
|
||||
@@ -1403,8 +1313,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sDaemonsetDesiredScheduledNodesKey,
|
||||
key: k8sDaemonsetDesiredScheduledNodesKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_DESIRED_SCHEDULED_NODES,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_DESIRED_SCHEDULED_NODES,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1417,8 +1327,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '2964eb92',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1432,8 +1342,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: k8sDaemonsetNameKey,
|
||||
key: k8sDaemonsetNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1450,8 +1360,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sDaemonsetCurrentScheduledNodesKey,
|
||||
key: k8sDaemonsetCurrentScheduledNodesKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_CURRENT_SCHEDULED_NODES,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_CURRENT_SCHEDULED_NODES,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1464,8 +1374,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: 'cd324eff',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1479,8 +1389,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: k8sDaemonsetNameKey,
|
||||
key: k8sDaemonsetNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1497,8 +1407,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sDaemonsetReadyNodesKey,
|
||||
key: k8sDaemonsetReadyNodesKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_READY_NODES,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_READY_NODES,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1511,8 +1421,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '0416fa6f',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1526,8 +1436,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: k8sDaemonsetNameKey,
|
||||
key: k8sDaemonsetNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1544,8 +1454,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sDaemonsetMisscheduledNodesKey,
|
||||
key: k8sDaemonsetMisscheduledNodesKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_MISSCHEDULED_NODES,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_MISSCHEDULED_NODES,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1558,8 +1468,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: 'c0a126d3',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1573,8 +1483,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: k8sDaemonsetNameKey,
|
||||
key: k8sDaemonsetNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1625,8 +1535,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sDeploymentDesiredKey,
|
||||
key: k8sDeploymentDesiredKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_DESIRED,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_DESIRED,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1639,8 +1549,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '9bc659c1',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1654,8 +1564,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: k8sDeploymentNameKey,
|
||||
key: k8sDeploymentNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1672,8 +1582,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: k8sDeploymentAvailableKey,
|
||||
key: k8sDeploymentAvailableKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_AVAILABLE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_AVAILABLE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1686,8 +1596,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: 'e1696631',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1701,8 +1611,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: k8sDeploymentNameKey,
|
||||
key: k8sDeploymentNameKey,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1758,21 +1668,14 @@ export const getNamespacePodMetricsQueryPayload = (
|
||||
namespace: InframonitoringtypesNamespaceRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
): GetQueryResultsProps[] => {
|
||||
const k8sNamespaceNameKey = dotMetricsEnabled
|
||||
? 'k8s.namespace.name'
|
||||
: 'k8s_namespace_name';
|
||||
|
||||
return getPodUtilizationByPodQueryPayloads(
|
||||
): GetQueryResultsProps[] =>
|
||||
getPodUtilizationByPodQueryPayloads(
|
||||
{
|
||||
workloadNameKey: k8sNamespaceNameKey,
|
||||
workloadNameKey: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
workloadNameValue: namespace.namespaceName ?? '',
|
||||
clusterName:
|
||||
namespace.meta?.[INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME] ?? '',
|
||||
},
|
||||
start,
|
||||
end,
|
||||
dotMetricsEnabled,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@ import { SelectedItemParams } from '../hooks';
|
||||
export const k8sNodeGetSelectedItemExpression = (
|
||||
params: SelectedItemParams,
|
||||
): string =>
|
||||
`k8s.node.name = ${formatValueForExpression(params.selectedItem ?? '')}`;
|
||||
`${INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME} = ${formatValueForExpression(params.selectedItem ?? '')}`;
|
||||
|
||||
export const k8sNodeDetailsMetadataConfig: K8sDetailsMetadataConfig<InframonitoringtypesNodeRecordDTO>[] =
|
||||
[
|
||||
@@ -111,89 +111,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
node: InframonitoringtypesNodeRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
): GetQueryResultsProps[] => {
|
||||
const getKey = (dotKey: string, underscoreKey: string): string =>
|
||||
dotMetricsEnabled ? dotKey : underscoreKey;
|
||||
const k8sNodeCpuUtilizationKey = getKey(
|
||||
'k8s.node.cpu.usage',
|
||||
'k8s_node_cpu_usage',
|
||||
);
|
||||
|
||||
const k8sNodeAllocatableCpuKey = getKey(
|
||||
'k8s.node.allocatable_cpu',
|
||||
'k8s_node_allocatable_cpu',
|
||||
);
|
||||
|
||||
const k8sContainerCpuRequestKey = getKey(
|
||||
'k8s.container.cpu_request',
|
||||
'k8s_container_cpu_request',
|
||||
);
|
||||
|
||||
const k8sNodeMemoryUsageKey = getKey(
|
||||
'k8s.node.memory.usage',
|
||||
'k8s_node_memory_usage',
|
||||
);
|
||||
|
||||
const k8sNodeAllocatableMemoryKey = getKey(
|
||||
'k8s.node.allocatable_memory',
|
||||
'k8s_node_allocatable_memory',
|
||||
);
|
||||
|
||||
const k8sContainerMemoryRequestKey = getKey(
|
||||
'k8s.container.memory_request',
|
||||
'k8s_container_memory_request',
|
||||
);
|
||||
|
||||
const k8sNodeMemoryWorkingSetKey = getKey(
|
||||
'k8s.node.memory.working_set',
|
||||
'k8s_node_memory_working_set',
|
||||
);
|
||||
|
||||
const k8sNodeMemoryRssKey = getKey(
|
||||
'k8s.node.memory.rss',
|
||||
'k8s_node_memory_rss',
|
||||
);
|
||||
|
||||
const k8sPodCpuUtilizationKey = getKey(
|
||||
'k8s.pod.cpu.usage',
|
||||
'k8s_pod_cpu_usage',
|
||||
);
|
||||
|
||||
const k8sPodMemoryUsageKey = getKey(
|
||||
'k8s.pod.memory.usage',
|
||||
'k8s_pod_memory_usage',
|
||||
);
|
||||
|
||||
const k8sNodeNetworkErrorsKey = getKey(
|
||||
'k8s.node.network.errors',
|
||||
'k8s_node_network_errors',
|
||||
);
|
||||
|
||||
const k8sNodeNetworkIoKey = getKey(
|
||||
'k8s.node.network.io',
|
||||
'k8s_node_network_io',
|
||||
);
|
||||
|
||||
const k8sNodeFilesystemUsageKey = getKey(
|
||||
'k8s.node.filesystem.usage',
|
||||
'k8s_node_filesystem_usage',
|
||||
);
|
||||
|
||||
const k8sNodeFilesystemCapacityKey = getKey(
|
||||
'k8s.node.filesystem.capacity',
|
||||
'k8s_node_filesystem_capacity',
|
||||
);
|
||||
|
||||
const k8sNodeFilesystemAvailableKey = getKey(
|
||||
'k8s.node.filesystem.available',
|
||||
'k8s_node_filesystem_available',
|
||||
);
|
||||
|
||||
const k8sNodeNameKey = getKey('k8s.node.name', 'k8s_node_name');
|
||||
|
||||
const k8sPodNameKey = getKey('k8s.pod.name', 'k8s_pod_name');
|
||||
|
||||
return [
|
||||
{
|
||||
selectedTime: 'GLOBAL_TIME',
|
||||
@@ -205,7 +123,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_cpu_usage--float64--Gauge--true',
|
||||
key: k8sNodeCpuUtilizationKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CPU_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -219,7 +137,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -244,7 +162,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_allocatable_cpu--float64--Gauge--true',
|
||||
key: k8sNodeAllocatableCpuKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_ALLOCATABLE_CPU,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -258,7 +176,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -283,7 +201,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_cpu_request--float64--Gauge--true',
|
||||
key: k8sContainerCpuRequestKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_REQUEST,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -297,7 +215,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -322,7 +240,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_cpu_usage--float64--Gauge--true',
|
||||
key: k8sNodeCpuUtilizationKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CPU_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -336,7 +254,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -361,7 +279,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_cpu_usage--float64--Gauge--true',
|
||||
key: k8sNodeCpuUtilizationKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CPU_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'min',
|
||||
@@ -375,7 +293,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -434,7 +352,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_memory_usage--float64--Gauge--true',
|
||||
key: k8sNodeMemoryUsageKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_MEMORY_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -448,7 +366,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -473,7 +391,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_allocatable_memory--float64--Gauge--true',
|
||||
key: k8sNodeAllocatableMemoryKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_ALLOCATABLE_MEMORY,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -487,7 +405,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -512,7 +430,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_memory_request--float64--Gauge--true',
|
||||
key: k8sContainerMemoryRequestKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_REQUEST,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -526,7 +444,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -551,7 +469,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_memory_usage--float64--Gauge--true',
|
||||
key: k8sNodeMemoryUsageKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_MEMORY_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -565,7 +483,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -590,7 +508,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_memory_usage--float64--Gauge--true',
|
||||
key: k8sNodeMemoryUsageKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_MEMORY_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'min',
|
||||
@@ -604,7 +522,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -629,7 +547,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_memory_working_set--float64--Gauge--true',
|
||||
key: k8sNodeMemoryWorkingSetKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_MEMORY_WORKING_SET,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -643,7 +561,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -668,7 +586,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_memory_rss--float64--Gauge--true',
|
||||
key: k8sNodeMemoryRssKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_MEMORY_RSS,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -682,7 +600,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -741,7 +659,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_cpu_usage--float64--Gauge--true',
|
||||
key: k8sNodeCpuUtilizationKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CPU_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -755,7 +673,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -780,7 +698,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_allocatable_cpu--float64--Gauge--true',
|
||||
key: k8sNodeAllocatableCpuKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_ALLOCATABLE_CPU,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -794,7 +712,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -819,7 +737,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_cpu_request--float64--Gauge--true',
|
||||
key: k8sContainerCpuRequestKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_REQUEST,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -833,7 +751,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -905,7 +823,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_memory_usage--float64--Gauge--true',
|
||||
key: k8sNodeMemoryUsageKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_MEMORY_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -919,7 +837,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -944,7 +862,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_allocatable_memory--float64--Gauge--true',
|
||||
key: k8sNodeAllocatableMemoryKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_ALLOCATABLE_MEMORY,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -958,7 +876,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -983,7 +901,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_memory_request--float64--Gauge--true',
|
||||
key: k8sContainerMemoryRequestKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_REQUEST,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -997,7 +915,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1069,7 +987,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_cpu_usage--float64--Gauge--true',
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1083,7 +1001,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1097,12 +1015,12 @@ export const getNodeMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: k8sPodNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
having: [],
|
||||
legend: `{{${k8sPodNameKey}}}`,
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}}}`,
|
||||
limit: 10,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
@@ -1149,7 +1067,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_memory_usage--float64--Gauge--true',
|
||||
key: k8sPodMemoryUsageKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1163,7 +1081,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1177,12 +1095,12 @@ export const getNodeMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: k8sPodNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
having: [],
|
||||
legend: `{{${k8sPodNameKey}}}`,
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}}}`,
|
||||
limit: 10,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
@@ -1229,7 +1147,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_network_errors--float64--Sum--true',
|
||||
key: k8sNodeNetworkErrorsKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NETWORK_ERRORS,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'increase',
|
||||
@@ -1243,7 +1161,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1315,7 +1233,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_network_io--float64--Sum--true',
|
||||
key: k8sNodeNetworkIoKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NETWORK_IO,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'rate',
|
||||
@@ -1329,7 +1247,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1401,7 +1319,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_filesystem_usage--float64--Gauge--true',
|
||||
key: k8sNodeFilesystemUsageKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_FILESYSTEM_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1415,7 +1333,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1440,7 +1358,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_filesystem_capacity--float64--Gauge--true',
|
||||
key: k8sNodeFilesystemCapacityKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_FILESYSTEM_CAPACITY,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1454,7 +1372,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1479,7 +1397,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_filesystem_available--float64--Gauge--true',
|
||||
key: k8sNodeFilesystemAvailableKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_FILESYSTEM_AVAILABLE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1493,7 +1411,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1552,7 +1470,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_filesystem_usage--float64--Gauge--true',
|
||||
key: k8sNodeFilesystemUsageKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_FILESYSTEM_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1566,7 +1484,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1591,7 +1509,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_filesystem_capacity--float64--Gauge--true',
|
||||
key: k8sNodeFilesystemCapacityKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_FILESYSTEM_CAPACITY,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1605,7 +1523,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: k8sNodeNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -113,21 +113,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
statefulSet: InframonitoringtypesStatefulSetRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
): GetQueryResultsProps[] => {
|
||||
const k8sStatefulSetNameKey = dotMetricsEnabled
|
||||
? INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME
|
||||
: 'k8s_statefulset_name';
|
||||
const k8sNamespaceNameKey = dotMetricsEnabled
|
||||
? INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME
|
||||
: 'k8s_namespace_name';
|
||||
const k8sPodNameKey = dotMetricsEnabled
|
||||
? INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME
|
||||
: 'k8s_pod_name';
|
||||
const k8sClusterNameKey = dotMetricsEnabled
|
||||
? INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME
|
||||
: 'k8s_cluster_name';
|
||||
|
||||
const clusterName =
|
||||
statefulSet.meta?.[INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME] ?? '';
|
||||
const namespaceName =
|
||||
@@ -139,7 +125,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -150,7 +136,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -158,45 +144,6 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
},
|
||||
];
|
||||
|
||||
const k8sPodCpuUtilKey = dotMetricsEnabled
|
||||
? 'k8s.pod.cpu.usage'
|
||||
: 'k8s_pod_cpu_usage';
|
||||
const k8sContainerCpuRequestKey = dotMetricsEnabled
|
||||
? 'k8s.container.cpu_request'
|
||||
: 'k8s_container_cpu_request';
|
||||
const k8sContainerCpuLimitKey = dotMetricsEnabled
|
||||
? 'k8s.container.cpu_limit'
|
||||
: 'k8s_container_cpu_limit';
|
||||
const k8sPodCpuReqUtilKey = dotMetricsEnabled
|
||||
? 'k8s.pod.cpu_request_utilization'
|
||||
: 'k8s_pod_cpu_request_utilization';
|
||||
const k8sPodCpuLimitUtilKey = dotMetricsEnabled
|
||||
? 'k8s.pod.cpu_limit_utilization'
|
||||
: 'k8s_pod_cpu_limit_utilization';
|
||||
|
||||
const k8sPodMemUsageKey = dotMetricsEnabled
|
||||
? 'k8s.pod.memory.usage'
|
||||
: 'k8s_pod_memory_usage';
|
||||
const k8sContainerMemRequestKey = dotMetricsEnabled
|
||||
? 'k8s.container.memory_request'
|
||||
: 'k8s_container_memory_request';
|
||||
const k8sContainerMemLimitKey = dotMetricsEnabled
|
||||
? 'k8s.container.memory_limit'
|
||||
: 'k8s_container_memory_limit';
|
||||
const k8sPodMemReqUtilKey = dotMetricsEnabled
|
||||
? 'k8s.pod.memory_request_utilization'
|
||||
: 'k8s_pod_memory_request_utilization';
|
||||
const k8sPodMemLimitUtilKey = dotMetricsEnabled
|
||||
? 'k8s.pod.memory_limit_utilization'
|
||||
: 'k8s_pod_memory_limit_utilization';
|
||||
|
||||
const k8sPodNetworkIoKey = dotMetricsEnabled
|
||||
? 'k8s.pod.network.io'
|
||||
: 'k8s_pod_network_io';
|
||||
const k8sPodNetworkErrorsKey = dotMetricsEnabled
|
||||
? 'k8s.pod.network.errors'
|
||||
: 'k8s_pod_network_errors';
|
||||
|
||||
return [
|
||||
{
|
||||
selectedTime: 'GLOBAL_TIME',
|
||||
@@ -208,7 +155,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'cpu_usage',
|
||||
key: k8sPodCpuUtilKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -222,7 +169,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'ss_name',
|
||||
key: k8sStatefulSetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -251,7 +198,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'cpu_request',
|
||||
key: k8sContainerCpuRequestKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_REQUEST,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -265,7 +212,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'pod_name',
|
||||
key: k8sPodNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -294,7 +241,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'cpu_limit',
|
||||
key: k8sContainerCpuLimitKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_LIMIT,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -308,7 +255,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'pod_name',
|
||||
key: k8sPodNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -357,7 +304,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'cpu_req_util',
|
||||
key: k8sPodCpuReqUtilKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_REQUEST_UTILIZATION,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -371,7 +318,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'ss_name',
|
||||
key: k8sStatefulSetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -400,7 +347,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'cpu_limit_util',
|
||||
key: k8sPodCpuLimitUtilKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_LIMIT_UTILIZATION,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -414,7 +361,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'ss_name',
|
||||
key: k8sStatefulSetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -463,7 +410,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'mem_usage',
|
||||
key: k8sPodMemUsageKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -477,7 +424,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'ss_name',
|
||||
key: k8sStatefulSetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -506,7 +453,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'mem_request',
|
||||
key: k8sContainerMemRequestKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_REQUEST,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -520,7 +467,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'pod_name',
|
||||
key: k8sPodNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -549,7 +496,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'mem_limit',
|
||||
key: k8sContainerMemLimitKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_LIMIT,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -563,7 +510,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'pod_name',
|
||||
key: k8sPodNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -612,7 +559,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'mem_req_util',
|
||||
key: k8sPodMemReqUtilKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_REQUEST_UTILIZATION,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -626,7 +573,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'ss_name',
|
||||
key: k8sStatefulSetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -655,7 +602,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'mem_limit_util',
|
||||
key: k8sPodMemLimitUtilKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_LIMIT_UTILIZATION,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -669,7 +616,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'ss_name',
|
||||
key: k8sStatefulSetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -718,7 +665,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'net_io',
|
||||
key: k8sPodNetworkIoKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_IO,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'rate',
|
||||
@@ -732,7 +679,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'ss_name',
|
||||
key: k8sStatefulSetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -794,7 +741,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'net_err',
|
||||
key: k8sPodNetworkErrorsKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_ERRORS,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'increase',
|
||||
@@ -808,7 +755,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'ss_name',
|
||||
key: k8sStatefulSetNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -867,15 +814,10 @@ export const getStatefulSetPodMetricsQueryPayload = (
|
||||
statefulSet: InframonitoringtypesStatefulSetRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
): GetQueryResultsProps[] => {
|
||||
const k8sStatefulSetNameKey = dotMetricsEnabled
|
||||
? INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME
|
||||
: 'k8s_statefulset_name';
|
||||
|
||||
return getPodUtilizationByPodQueryPayloads(
|
||||
{
|
||||
workloadNameKey: k8sStatefulSetNameKey,
|
||||
workloadNameKey: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
workloadNameValue:
|
||||
statefulSet.meta?.[INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME] ?? '',
|
||||
clusterName:
|
||||
@@ -885,6 +827,5 @@ export const getStatefulSetPodMetricsQueryPayload = (
|
||||
},
|
||||
start,
|
||||
end,
|
||||
dotMetricsEnabled,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -97,36 +97,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
volume: InframonitoringtypesVolumeRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
): GetQueryResultsProps[] => {
|
||||
const k8sClusterNameKey = dotMetricsEnabled
|
||||
? INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME
|
||||
: 'k8s_cluster_name';
|
||||
const k8sNamespaceNameKey = dotMetricsEnabled
|
||||
? INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME
|
||||
: 'k8s_namespace_name';
|
||||
const k8sVolumeAvailableKey = dotMetricsEnabled
|
||||
? INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_AVAILABLE
|
||||
: 'k8s_volume_available';
|
||||
const k8sVolumeCapacityKey = dotMetricsEnabled
|
||||
? INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_CAPACITY
|
||||
: 'k8s_volume_capacity';
|
||||
const k8sVolumeInodesUsedKey = dotMetricsEnabled
|
||||
? INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_INODES_USED
|
||||
: 'k8s_volume_inodes_used';
|
||||
const k8sVolumeInodesKey = dotMetricsEnabled
|
||||
? INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_INODES
|
||||
: 'k8s_volume_inodes';
|
||||
const k8sVolumeInodesFreeKey = dotMetricsEnabled
|
||||
? INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_INODES_FREE
|
||||
: 'k8s_volume_inodes_free';
|
||||
const k8sVolumeTypeKey = dotMetricsEnabled
|
||||
? INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_TYPE
|
||||
: 'k8s_volume_type';
|
||||
const k8sPVCNameKey = dotMetricsEnabled
|
||||
? INFRA_MONITORING_ATTR_KEYS.K8S_PERSISTENT_VOLUME_CLAIM_NAME
|
||||
: 'k8s_persistentvolumeclaim_name';
|
||||
|
||||
return [
|
||||
{
|
||||
selectedTime: 'GLOBAL_TIME',
|
||||
@@ -138,7 +109,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_volume_available--float64--Gauge--true',
|
||||
key: k8sVolumeAvailableKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_AVAILABLE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -152,7 +123,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -164,7 +135,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -177,7 +148,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_volume_type--string--tag--false',
|
||||
key: k8sVolumeTypeKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_TYPE,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -188,7 +159,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_persistentvolumeclaim_name--string--tag--false',
|
||||
key: k8sPVCNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_PERSISTENT_VOLUME_CLAIM_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -233,7 +204,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_volume_capacity--float64--Gauge--true',
|
||||
key: k8sVolumeCapacityKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_CAPACITY,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -247,7 +218,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -259,7 +230,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -272,7 +243,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_volume_type--string--tag--false',
|
||||
key: k8sVolumeTypeKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_TYPE,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -283,7 +254,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_persistentvolumeclaim_name--string--tag--false',
|
||||
key: k8sPVCNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_PERSISTENT_VOLUME_CLAIM_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -328,7 +299,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_volume_inodes_used--float64--Gauge--true',
|
||||
key: k8sVolumeInodesUsedKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_INODES_USED,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -342,7 +313,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -354,7 +325,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -367,7 +338,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_volume_type--string--tag--false',
|
||||
key: k8sVolumeTypeKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_TYPE,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -378,7 +349,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_persistentvolumeclaim_name--string--tag--false',
|
||||
key: k8sPVCNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_PERSISTENT_VOLUME_CLAIM_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -423,7 +394,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_volume_inodes--float64--Gauge--true',
|
||||
key: k8sVolumeInodesKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_INODES,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -437,7 +408,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -449,7 +420,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -462,7 +433,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_volume_type--string--tag--false',
|
||||
key: k8sVolumeTypeKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_TYPE,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -473,7 +444,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_persistentvolumeclaim_name--string--tag--false',
|
||||
key: k8sPVCNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_PERSISTENT_VOLUME_CLAIM_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -518,7 +489,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_volume_inodes_free--float64--Gauge--true',
|
||||
key: k8sVolumeInodesFreeKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_INODES_FREE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -532,7 +503,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: k8sClusterNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -544,7 +515,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: k8sNamespaceNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -557,7 +528,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_volume_type--string--tag--false',
|
||||
key: k8sVolumeTypeKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_TYPE,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -568,7 +539,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_persistentvolumeclaim_name--string--tag--false',
|
||||
key: k8sPVCNameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_PERSISTENT_VOLUME_CLAIM_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
|
||||
@@ -61,6 +61,10 @@ export const INFRA_MONITORING_ATTR_KEYS = {
|
||||
K8S_CONTAINER_CPU_LIMIT: 'k8s.container.cpu_limit',
|
||||
K8S_CONTAINER_MEMORY_REQUEST: 'k8s.container.memory_request',
|
||||
K8S_CONTAINER_MEMORY_LIMIT: 'k8s.container.memory_limit',
|
||||
CONTAINER_CPU_USAGE: 'container.cpu.usage',
|
||||
CONTAINER_MEMORY_USAGE: 'container.memory.usage',
|
||||
CONTAINER_MEMORY_WORKING_SET: 'container.memory.working_set',
|
||||
CONTAINER_MEMORY_RSS: 'container.memory.rss',
|
||||
|
||||
// Deployment
|
||||
K8S_DEPLOYMENT_NAME: 'k8s.deployment.name',
|
||||
@@ -109,6 +113,10 @@ export const INFRA_MONITORING_ATTR_KEYS = {
|
||||
|
||||
// Environment
|
||||
DEPLOYMENT_ENVIRONMENT: 'deployment.environment',
|
||||
|
||||
// Host System
|
||||
OS_TYPE: 'os.type',
|
||||
SYSTEM_CPU_LOAD_AVERAGE_15M: 'system.cpu.load_average.15m',
|
||||
} as const;
|
||||
|
||||
export const DEFAULT_PAGE_SIZE = 10;
|
||||
@@ -159,81 +167,48 @@ export const K8sCategories = {
|
||||
VOLUMES: 'volumes',
|
||||
};
|
||||
|
||||
const underscoreMap = {
|
||||
[InfraMonitoringEntity.HOSTS]: 'system_cpu_load_average_15m',
|
||||
[InfraMonitoringEntity.PODS]: 'k8s_pod_cpu_usage',
|
||||
[InfraMonitoringEntity.NODES]: 'k8s_node_cpu_usage',
|
||||
[InfraMonitoringEntity.NAMESPACES]: 'k8s_pod_cpu_usage',
|
||||
[InfraMonitoringEntity.CLUSTERS]: 'k8s_node_cpu_usage',
|
||||
[InfraMonitoringEntity.DEPLOYMENTS]: 'k8s_pod_cpu_usage',
|
||||
[InfraMonitoringEntity.STATEFULSETS]: 'k8s_pod_cpu_usage',
|
||||
[InfraMonitoringEntity.DAEMONSETS]: 'k8s_pod_cpu_usage',
|
||||
[InfraMonitoringEntity.CONTAINERS]: 'k8s_pod_cpu_usage',
|
||||
[InfraMonitoringEntity.JOBS]: 'k8s_job_desired_successful_pods',
|
||||
[InfraMonitoringEntity.VOLUMES]: 'k8s_volume_capacity',
|
||||
};
|
||||
|
||||
const dotMap = {
|
||||
[InfraMonitoringEntity.HOSTS]: 'system.cpu.load_average.15m',
|
||||
[InfraMonitoringEntity.PODS]: 'k8s.pod.cpu.usage',
|
||||
[InfraMonitoringEntity.NODES]: 'k8s.node.cpu.usage',
|
||||
[InfraMonitoringEntity.NAMESPACES]: 'k8s.pod.cpu.usage',
|
||||
[InfraMonitoringEntity.CLUSTERS]: 'k8s.node.cpu.usage',
|
||||
[InfraMonitoringEntity.DEPLOYMENTS]: 'k8s.pod.cpu.usage',
|
||||
[InfraMonitoringEntity.STATEFULSETS]: 'k8s.pod.cpu.usage',
|
||||
[InfraMonitoringEntity.DAEMONSETS]: 'k8s.pod.cpu.usage',
|
||||
[InfraMonitoringEntity.CONTAINERS]: 'k8s.pod.cpu.usage',
|
||||
[InfraMonitoringEntity.JOBS]: 'k8s.job.desired_successful_pods',
|
||||
[InfraMonitoringEntity.VOLUMES]: 'k8s.volume.capacity',
|
||||
[InfraMonitoringEntity.HOSTS]:
|
||||
INFRA_MONITORING_ATTR_KEYS.SYSTEM_CPU_LOAD_AVERAGE_15M,
|
||||
[InfraMonitoringEntity.PODS]: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
[InfraMonitoringEntity.NODES]: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CPU_USAGE,
|
||||
[InfraMonitoringEntity.NAMESPACES]:
|
||||
INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
[InfraMonitoringEntity.CLUSTERS]:
|
||||
INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CPU_USAGE,
|
||||
[InfraMonitoringEntity.DEPLOYMENTS]:
|
||||
INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
[InfraMonitoringEntity.STATEFULSETS]:
|
||||
INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
[InfraMonitoringEntity.DAEMONSETS]:
|
||||
INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
[InfraMonitoringEntity.CONTAINERS]:
|
||||
INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
[InfraMonitoringEntity.JOBS]:
|
||||
INFRA_MONITORING_ATTR_KEYS.K8S_JOB_DESIRED_SUCCESSFUL_PODS,
|
||||
[InfraMonitoringEntity.VOLUMES]:
|
||||
INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_CAPACITY,
|
||||
};
|
||||
|
||||
export function GetK8sEntityToAggregateAttribute(
|
||||
category: InfraMonitoringEntity,
|
||||
dotMetricsEnabled: boolean,
|
||||
): string {
|
||||
return dotMetricsEnabled ? dotMap[category] : underscoreMap[category];
|
||||
return dotMap[category];
|
||||
}
|
||||
|
||||
export function GetPodsQuickFiltersConfig(
|
||||
dotMetricsEnabled: boolean,
|
||||
): IQuickFiltersConfig[] {
|
||||
const podKey = dotMetricsEnabled ? 'k8s.pod.name' : 'k8s_pod_name';
|
||||
const namespaceKey = dotMetricsEnabled
|
||||
? 'k8s.namespace.name'
|
||||
: 'k8s_namespace_name';
|
||||
const nodeKey = dotMetricsEnabled ? 'k8s.node.name' : 'k8s_node_name';
|
||||
const clusterKey = dotMetricsEnabled ? 'k8s.cluster.name' : 'k8s_cluster_name';
|
||||
const deploymentKey = dotMetricsEnabled
|
||||
? 'k8s.deployment.name'
|
||||
: 'k8s_deployment_name';
|
||||
const statefulsetKey = dotMetricsEnabled
|
||||
? 'k8s.statefulset.name'
|
||||
: 'k8s_statefulset_name';
|
||||
const daemonsetKey = dotMetricsEnabled
|
||||
? 'k8s.daemonset.name'
|
||||
: 'k8s_daemonset_name';
|
||||
const jobKey = dotMetricsEnabled ? 'k8s.job.name' : 'k8s_job_name';
|
||||
const environmentKey = dotMetricsEnabled
|
||||
? 'deployment.environment'
|
||||
: 'deployment_environment';
|
||||
|
||||
// Define aggregate attribute (metric) name
|
||||
const cpuUtilizationMetric = dotMetricsEnabled
|
||||
? 'k8s.pod.cpu.usage'
|
||||
: 'k8s_pod_cpu_usage';
|
||||
|
||||
export function GetPodsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Pod',
|
||||
attributeKey: {
|
||||
key: podKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'tag',
|
||||
id: `${podKey}--string--tag--true`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}--string--tag--true`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: cpuUtilizationMetric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -241,13 +216,13 @@ export function GetPodsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Namespace',
|
||||
attributeKey: {
|
||||
key: namespaceKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${namespaceKey}--string--resource--false`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME}--string--resource--false`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: cpuUtilizationMetric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: false,
|
||||
},
|
||||
@@ -255,13 +230,13 @@ export function GetPodsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Node',
|
||||
attributeKey: {
|
||||
key: nodeKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${nodeKey}--string--resource--false`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME}--string--resource--false`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: cpuUtilizationMetric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: false,
|
||||
},
|
||||
@@ -269,13 +244,13 @@ export function GetPodsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Cluster',
|
||||
attributeKey: {
|
||||
key: clusterKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${clusterKey}--string--resource--false`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME}--string--resource--false`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: cpuUtilizationMetric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: false,
|
||||
},
|
||||
@@ -283,13 +258,13 @@ export function GetPodsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Deployment',
|
||||
attributeKey: {
|
||||
key: deploymentKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${deploymentKey}--string--resource--false`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME}--string--resource--false`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: cpuUtilizationMetric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: false,
|
||||
},
|
||||
@@ -297,13 +272,13 @@ export function GetPodsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Statefulset',
|
||||
attributeKey: {
|
||||
key: statefulsetKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${statefulsetKey}--string--resource--false`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME}--string--resource--false`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: cpuUtilizationMetric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: false,
|
||||
},
|
||||
@@ -311,13 +286,13 @@ export function GetPodsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'DaemonSet',
|
||||
attributeKey: {
|
||||
key: daemonsetKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${daemonsetKey}--string--resource--false`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME}--string--resource--false`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: cpuUtilizationMetric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: false,
|
||||
},
|
||||
@@ -325,13 +300,13 @@ export function GetPodsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Job',
|
||||
attributeKey: {
|
||||
key: jobKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${jobKey}--string--resource--false`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME}--string--resource--false`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: cpuUtilizationMetric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: false,
|
||||
},
|
||||
@@ -339,7 +314,7 @@ export function GetPodsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: environmentKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
@@ -348,33 +323,19 @@ export function GetPodsQuickFiltersConfig(
|
||||
];
|
||||
}
|
||||
|
||||
export function GetNodesQuickFiltersConfig(
|
||||
dotMetricsEnabled: boolean,
|
||||
): IQuickFiltersConfig[] {
|
||||
// Define attribute keys
|
||||
const nodeKey = dotMetricsEnabled ? 'k8s.node.name' : 'k8s_node_name';
|
||||
const clusterKey = dotMetricsEnabled ? 'k8s.cluster.name' : 'k8s_cluster_name';
|
||||
|
||||
// Define aggregate metric name for node CPU utilization
|
||||
const cpuUtilMetric = dotMetricsEnabled
|
||||
? 'k8s.node.cpu.usage'
|
||||
: 'k8s_node_cpu_usage';
|
||||
const environmentKey = dotMetricsEnabled
|
||||
? 'deployment.environment'
|
||||
: 'deployment_environment';
|
||||
|
||||
export function GetNodesQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Node Name',
|
||||
attributeKey: {
|
||||
key: nodeKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${nodeKey}--string--resource--true`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME}--string--resource--true`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: cpuUtilMetric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -382,13 +343,13 @@ export function GetNodesQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Cluster Name',
|
||||
attributeKey: {
|
||||
key: clusterKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${clusterKey}--string--resource--true`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME}--string--resource--true`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: cpuUtilMetric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -396,7 +357,7 @@ export function GetNodesQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: environmentKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
@@ -405,32 +366,19 @@ export function GetNodesQuickFiltersConfig(
|
||||
];
|
||||
}
|
||||
|
||||
export function GetNamespaceQuickFiltersConfig(
|
||||
dotMetricsEnabled: boolean,
|
||||
): IQuickFiltersConfig[] {
|
||||
const namespaceKey = dotMetricsEnabled
|
||||
? 'k8s.namespace.name'
|
||||
: 'k8s_namespace_name';
|
||||
const clusterKey = dotMetricsEnabled ? 'k8s.cluster.name' : 'k8s_cluster_name';
|
||||
const cpuUtilMetric = dotMetricsEnabled
|
||||
? 'k8s.pod.cpu.usage'
|
||||
: 'k8s_pod_cpu_usage';
|
||||
const environmentKey = dotMetricsEnabled
|
||||
? 'deployment.environment'
|
||||
: 'deployment_environment';
|
||||
|
||||
export function GetNamespaceQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Namespace Name',
|
||||
attributeKey: {
|
||||
key: namespaceKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${namespaceKey}--string--resource`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: cpuUtilMetric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -438,13 +386,13 @@ export function GetNamespaceQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Cluster Name',
|
||||
attributeKey: {
|
||||
key: clusterKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${clusterKey}--string--resource`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: cpuUtilMetric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -452,7 +400,7 @@ export function GetNamespaceQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: environmentKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
@@ -461,29 +409,19 @@ export function GetNamespaceQuickFiltersConfig(
|
||||
];
|
||||
}
|
||||
|
||||
export function GetClustersQuickFiltersConfig(
|
||||
dotMetricsEnabled: boolean,
|
||||
): IQuickFiltersConfig[] {
|
||||
const clusterKey = dotMetricsEnabled ? 'k8s.cluster.name' : 'k8s_cluster_name';
|
||||
const cpuUtilMetric = dotMetricsEnabled
|
||||
? 'k8s.node.cpu.usage'
|
||||
: 'k8s_node_cpu_usage';
|
||||
const environmentKey = dotMetricsEnabled
|
||||
? 'deployment.environment'
|
||||
: 'deployment_environment';
|
||||
|
||||
export function GetClustersQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Cluster Name',
|
||||
attributeKey: {
|
||||
key: clusterKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${clusterKey}--string--resource`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: cpuUtilMetric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -491,7 +429,7 @@ export function GetClustersQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: environmentKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
@@ -500,35 +438,19 @@ export function GetClustersQuickFiltersConfig(
|
||||
];
|
||||
}
|
||||
|
||||
export function GetVolumesQuickFiltersConfig(
|
||||
dotMetricsEnabled: boolean,
|
||||
): IQuickFiltersConfig[] {
|
||||
const pvcKey = dotMetricsEnabled
|
||||
? 'k8s.persistentvolumeclaim.name'
|
||||
: 'k8s_persistentvolumeclaim_name';
|
||||
const namespaceKey = dotMetricsEnabled
|
||||
? 'k8s.namespace.name'
|
||||
: 'k8s_namespace_name';
|
||||
const clusterKey = dotMetricsEnabled ? 'k8s.cluster.name' : 'k8s_cluster_name';
|
||||
const volumeMetric = dotMetricsEnabled
|
||||
? 'k8s.volume.capacity'
|
||||
: 'k8s_volume_capacity';
|
||||
const environmentKey = dotMetricsEnabled
|
||||
? 'deployment.environment'
|
||||
: 'deployment_environment';
|
||||
|
||||
export function GetVolumesQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'PVC Volume Claim Name',
|
||||
attributeKey: {
|
||||
key: pvcKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_PERSISTENT_VOLUME_CLAIM_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${pvcKey}--string--resource`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_PERSISTENT_VOLUME_CLAIM_NAME}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: volumeMetric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_CAPACITY,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -536,13 +458,13 @@ export function GetVolumesQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Namespace Name',
|
||||
attributeKey: {
|
||||
key: namespaceKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${namespaceKey}--string--resource`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: volumeMetric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_CAPACITY,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -550,13 +472,13 @@ export function GetVolumesQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Cluster Name',
|
||||
attributeKey: {
|
||||
key: clusterKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${clusterKey}--string--resource`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: volumeMetric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_CAPACITY,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -564,7 +486,7 @@ export function GetVolumesQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: environmentKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
@@ -573,33 +495,19 @@ export function GetVolumesQuickFiltersConfig(
|
||||
];
|
||||
}
|
||||
|
||||
export function GetDeploymentsQuickFiltersConfig(
|
||||
dotMetricsEnabled: boolean,
|
||||
): IQuickFiltersConfig[] {
|
||||
const deployKey = dotMetricsEnabled
|
||||
? 'k8s.deployment.name'
|
||||
: 'k8s_deployment_name';
|
||||
const namespaceKey = dotMetricsEnabled
|
||||
? 'k8s.namespace.name'
|
||||
: 'k8s_namespace_name';
|
||||
const clusterKey = dotMetricsEnabled ? 'k8s.cluster.name' : 'k8s_cluster_name';
|
||||
const metric = dotMetricsEnabled ? 'k8s.pod.cpu.usage' : 'k8s_pod_cpu_usage';
|
||||
const environmentKey = dotMetricsEnabled
|
||||
? 'deployment.environment'
|
||||
: 'deployment_environment';
|
||||
|
||||
export function GetDeploymentsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Deployment Name',
|
||||
attributeKey: {
|
||||
key: deployKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${deployKey}--string--resource`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: metric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -607,13 +515,13 @@ export function GetDeploymentsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Namespace Name',
|
||||
attributeKey: {
|
||||
key: namespaceKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${namespaceKey}--string--resource`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: metric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -621,13 +529,13 @@ export function GetDeploymentsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Cluster Name',
|
||||
attributeKey: {
|
||||
key: clusterKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${clusterKey}--string--resource`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: metric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -635,7 +543,7 @@ export function GetDeploymentsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: environmentKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
@@ -644,33 +552,19 @@ export function GetDeploymentsQuickFiltersConfig(
|
||||
];
|
||||
}
|
||||
|
||||
export function GetStatefulsetsQuickFiltersConfig(
|
||||
dotMetricsEnabled: boolean,
|
||||
): IQuickFiltersConfig[] {
|
||||
const ssKey = dotMetricsEnabled
|
||||
? 'k8s.statefulset.name'
|
||||
: 'k8s_statefulset_name';
|
||||
const namespaceKey = dotMetricsEnabled
|
||||
? 'k8s.namespace.name'
|
||||
: 'k8s_namespace_name';
|
||||
const clusterKey = dotMetricsEnabled ? 'k8s.cluster.name' : 'k8s_cluster_name';
|
||||
const metric = dotMetricsEnabled ? 'k8s.pod.cpu.usage' : 'k8s_pod_cpu_usage';
|
||||
const environmentKey = dotMetricsEnabled
|
||||
? 'deployment.environment'
|
||||
: 'deployment_environment';
|
||||
|
||||
export function GetStatefulsetsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Statefulset Name',
|
||||
attributeKey: {
|
||||
key: ssKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${ssKey}--string--resource`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: metric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -678,13 +572,13 @@ export function GetStatefulsetsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Namespace Name',
|
||||
attributeKey: {
|
||||
key: namespaceKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${namespaceKey}--string--resource`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: metric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -692,13 +586,13 @@ export function GetStatefulsetsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Cluster Name',
|
||||
attributeKey: {
|
||||
key: clusterKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${clusterKey}--string--resource`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: metric,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -706,7 +600,7 @@ export function GetStatefulsetsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: environmentKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
@@ -715,35 +609,19 @@ export function GetStatefulsetsQuickFiltersConfig(
|
||||
];
|
||||
}
|
||||
|
||||
export function GetDaemonsetsQuickFiltersConfig(
|
||||
dotMetricsEnabled: boolean,
|
||||
): IQuickFiltersConfig[] {
|
||||
const nameKey = dotMetricsEnabled
|
||||
? 'k8s.daemonset.name'
|
||||
: 'k8s_daemonset_name';
|
||||
const namespaceKey = dotMetricsEnabled
|
||||
? 'k8s.namespace.name'
|
||||
: 'k8s_namespace_name';
|
||||
const clusterKey = dotMetricsEnabled ? 'k8s.cluster.name' : 'k8s_cluster_name';
|
||||
const metricName = dotMetricsEnabled
|
||||
? 'k8s.pod.cpu.usage'
|
||||
: 'k8s_pod_cpu_usage';
|
||||
const environmentKey = dotMetricsEnabled
|
||||
? 'deployment.environment'
|
||||
: 'deployment_environment';
|
||||
|
||||
export function GetDaemonsetsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'DaemonSet Name',
|
||||
attributeKey: {
|
||||
key: nameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${nameKey}--string--resource--true`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME}--string--resource--true`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: metricName,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -751,12 +629,12 @@ export function GetDaemonsetsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Namespace Name',
|
||||
attributeKey: {
|
||||
key: namespaceKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: metricName,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -764,12 +642,12 @@ export function GetDaemonsetsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Cluster Name',
|
||||
attributeKey: {
|
||||
key: clusterKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: metricName,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -777,7 +655,7 @@ export function GetDaemonsetsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: environmentKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
@@ -786,33 +664,19 @@ export function GetDaemonsetsQuickFiltersConfig(
|
||||
];
|
||||
}
|
||||
|
||||
export function GetJobsQuickFiltersConfig(
|
||||
dotMetricsEnabled: boolean,
|
||||
): IQuickFiltersConfig[] {
|
||||
const nameKey = dotMetricsEnabled ? 'k8s.job.name' : 'k8s_job_name';
|
||||
const namespaceKey = dotMetricsEnabled
|
||||
? 'k8s.namespace.name'
|
||||
: 'k8s_namespace_name';
|
||||
const clusterKey = dotMetricsEnabled ? 'k8s.cluster.name' : 'k8s_cluster_name';
|
||||
const metricName = dotMetricsEnabled
|
||||
? 'k8s.pod.cpu.usage'
|
||||
: 'k8s_pod_cpu_usage';
|
||||
const environmentKey = dotMetricsEnabled
|
||||
? 'deployment.environment'
|
||||
: 'deployment_environment';
|
||||
|
||||
export function GetJobsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Job Name',
|
||||
attributeKey: {
|
||||
key: nameKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${nameKey}--string--resource--true`,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME}--string--resource--true`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: metricName,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -820,12 +684,12 @@ export function GetJobsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Namespace Name',
|
||||
attributeKey: {
|
||||
key: namespaceKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: metricName,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -833,12 +697,12 @@ export function GetJobsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Cluster Name',
|
||||
attributeKey: {
|
||||
key: clusterKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: metricName,
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -846,7 +710,7 @@ export function GetJobsQuickFiltersConfig(
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: environmentKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
@@ -965,39 +829,7 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
context: WorkloadFilterContext,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
): GetQueryResultsProps[] {
|
||||
const getKey = (dotKey: string, underscoreKey: string): string =>
|
||||
dotMetricsEnabled ? dotKey : underscoreKey;
|
||||
|
||||
const k8sPodCpuLimitUtilKey = getKey(
|
||||
'k8s.pod.cpu_limit_utilization',
|
||||
'k8s_pod_cpu_limit_utilization',
|
||||
);
|
||||
const k8sPodCpuRequestUtilKey = getKey(
|
||||
'k8s.pod.cpu_request_utilization',
|
||||
'k8s_pod_cpu_request_utilization',
|
||||
);
|
||||
const k8sPodMemLimitUtilKey = getKey(
|
||||
'k8s.pod.memory_limit_utilization',
|
||||
'k8s_pod_memory_limit_utilization',
|
||||
);
|
||||
const k8sPodMemRequestUtilKey = getKey(
|
||||
'k8s.pod.memory_request_utilization',
|
||||
'k8s_pod_memory_request_utilization',
|
||||
);
|
||||
const k8sPodFsUsageKey = getKey(
|
||||
'k8s.pod.filesystem.usage',
|
||||
'k8s_pod_filesystem_usage',
|
||||
);
|
||||
const k8sPodFsCapacityKey = getKey(
|
||||
'k8s.pod.filesystem.capacity',
|
||||
'k8s_pod_filesystem_capacity',
|
||||
);
|
||||
const k8sPodNameKey = getKey('k8s.pod.name', 'k8s_pod_name');
|
||||
const k8sClusterNameKey = getKey('k8s.cluster.name', 'k8s_cluster_name');
|
||||
const k8sNamespaceNameKey = getKey('k8s.namespace.name', 'k8s_namespace_name');
|
||||
|
||||
const baseFilters = [
|
||||
{
|
||||
id: 'workload',
|
||||
@@ -1014,8 +846,8 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
id: 'cluster',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: `${k8sClusterNameKey}--string--tag--false`,
|
||||
key: k8sClusterNameKey,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME}--string--tag--false`,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1027,8 +859,8 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
id: 'namespace',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: `${k8sNamespaceNameKey}--string--tag--false`,
|
||||
key: k8sNamespaceNameKey,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME}--string--tag--false`,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1041,8 +873,8 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
const podNameGroupBy = [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: `${k8sPodNameKey}--string--tag--false`,
|
||||
key: k8sPodNameKey,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}--string--tag--false`,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
type: 'tag',
|
||||
},
|
||||
];
|
||||
@@ -1074,7 +906,7 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
functions: [],
|
||||
groupBy: podNameGroupBy,
|
||||
having: [],
|
||||
legend: `{{${k8sPodNameKey}}}`,
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}}}`,
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
@@ -1108,7 +940,7 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'fs_usage',
|
||||
key: k8sPodFsUsageKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_FILESYSTEM_USAGE,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1122,7 +954,7 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
functions: [],
|
||||
groupBy: podNameGroupBy,
|
||||
having: [],
|
||||
legend: `{{${k8sPodNameKey}}}`,
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}}}`,
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
@@ -1135,7 +967,7 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'fs_capacity',
|
||||
key: k8sPodFsCapacityKey,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_FILESYSTEM_CAPACITY,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1149,7 +981,7 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
functions: [],
|
||||
groupBy: podNameGroupBy,
|
||||
having: [],
|
||||
legend: `{{${k8sPodNameKey}}}`,
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}}}`,
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
@@ -1163,7 +995,7 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
{
|
||||
disabled: false,
|
||||
expression: 'A/B',
|
||||
legend: `{{${k8sPodNameKey}}}`,
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}}}`,
|
||||
queryName: 'F1',
|
||||
},
|
||||
],
|
||||
@@ -1181,10 +1013,22 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
};
|
||||
|
||||
return [
|
||||
buildSingleMetricQuery(k8sPodCpuLimitUtilKey, 'cpu_limit_util'),
|
||||
buildSingleMetricQuery(k8sPodCpuRequestUtilKey, 'cpu_request_util'),
|
||||
buildSingleMetricQuery(k8sPodMemLimitUtilKey, 'mem_limit_util'),
|
||||
buildSingleMetricQuery(k8sPodMemRequestUtilKey, 'mem_request_util'),
|
||||
buildSingleMetricQuery(
|
||||
INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_LIMIT_UTILIZATION,
|
||||
'cpu_limit_util',
|
||||
),
|
||||
buildSingleMetricQuery(
|
||||
INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_REQUEST_UTILIZATION,
|
||||
'cpu_request_util',
|
||||
),
|
||||
buildSingleMetricQuery(
|
||||
INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_LIMIT_UTILIZATION,
|
||||
'mem_limit_util',
|
||||
),
|
||||
buildSingleMetricQuery(
|
||||
INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_REQUEST_UTILIZATION,
|
||||
'mem_request_util',
|
||||
),
|
||||
filesystemUsagePercentQuery,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ export function useCreateExportDashboard({
|
||||
layouts: [],
|
||||
panels: {},
|
||||
variables: [],
|
||||
links: [],
|
||||
},
|
||||
}),
|
||||
{
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
import 'tests/blob-polyfill';
|
||||
|
||||
import { fetchExportData } from 'api/v1/download/downloadExportData';
|
||||
import { prepareQueryRangePayloadV5 } from 'api/v5/v5';
|
||||
import { downloadFile } from 'lib/exportData/downloadFile';
|
||||
import { ExportFormat } from 'lib/exportData/types';
|
||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||
|
||||
import { runChunkedExport } from '../runChunkedExport';
|
||||
|
||||
jest.mock('api/v1/download/downloadExportData', () => ({
|
||||
fetchExportData: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('api/v5/v5', () => ({
|
||||
prepareQueryRangePayloadV5: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('lib/exportData/downloadFile', () => ({
|
||||
downloadFile: jest.fn(),
|
||||
getTimestampedFileName: jest.fn(
|
||||
(base: string, ext: string) => `${base}.${ext}`,
|
||||
),
|
||||
}));
|
||||
|
||||
const mockFetch = fetchExportData as jest.Mock;
|
||||
const mockPreparePayload = prepareQueryRangePayloadV5 as jest.Mock;
|
||||
const mockDownloadFile = downloadFile as jest.Mock;
|
||||
|
||||
// Minimal query shape — the runner only maps over builder.queryData.
|
||||
const query = {
|
||||
builder: { queryData: [{}] },
|
||||
} as unknown as Query;
|
||||
|
||||
const baseArgs = {
|
||||
query,
|
||||
timeRange: { start: 100, end: 200 },
|
||||
fileNameBase: 'trace-x',
|
||||
format: ExportFormat.Csv,
|
||||
onProgress: jest.fn(),
|
||||
};
|
||||
|
||||
// EXPORT_PAGE_SIZE is 50_000; rows → parts: 120k → 3, 40k → 1, etc.
|
||||
const rowsForParts = (parts: number): number => parts * 50_000;
|
||||
|
||||
function runArgs(
|
||||
overrides: Partial<Parameters<typeof runChunkedExport>[0]> = {},
|
||||
): Parameters<typeof runChunkedExport>[0] {
|
||||
return {
|
||||
...baseArgs,
|
||||
totalRows: rowsForParts(1),
|
||||
signal: new AbortController().signal,
|
||||
onProgress: jest.fn(),
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
async function savedFileText(): Promise<string> {
|
||||
expect(mockDownloadFile).toHaveBeenCalledTimes(1);
|
||||
const [blob] = mockDownloadFile.mock.calls[0];
|
||||
return (blob as Blob).text();
|
||||
}
|
||||
|
||||
describe('runChunkedExport', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
mockPreparePayload.mockImplementation(({ query: pageQuery }) => ({
|
||||
// Echo the page offset so fetch calls can be asserted per page.
|
||||
queryPayload: { offset: pageQuery.builder.queryData[0].offset },
|
||||
}));
|
||||
});
|
||||
|
||||
it('fetches one page for small exports and saves the file', async () => {
|
||||
mockFetch.mockResolvedValueOnce(new Blob(['h\na,b\n']));
|
||||
const onProgress = jest.fn();
|
||||
|
||||
await runChunkedExport(runArgs({ totalRows: 40_000, onProgress }));
|
||||
|
||||
expect(mockFetch).toHaveBeenCalledTimes(1);
|
||||
expect(mockFetch.mock.calls[0][0].body).toStrictEqual({ offset: 0 });
|
||||
expect(onProgress).toHaveBeenCalledWith(100);
|
||||
await expect(savedFileText()).resolves.toBe('h\na,b\n');
|
||||
});
|
||||
|
||||
it('fetches every page with the right offsets and stitches in order', async () => {
|
||||
mockFetch.mockImplementation(({ body }) =>
|
||||
Promise.resolve(new Blob([`h\nrow-${body.offset}\n`])),
|
||||
);
|
||||
|
||||
await runChunkedExport(runArgs({ totalRows: rowsForParts(3) }));
|
||||
|
||||
const offsets = mockFetch.mock.calls.map(([props]) => props.body.offset);
|
||||
expect(offsets.sort((a, b) => a - b)).toStrictEqual([0, 50_000, 100_000]);
|
||||
await expect(savedFileText()).resolves.toBe(
|
||||
'h\nrow-0\nrow-50000\nrow-100000\n',
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps page order even when later pages resolve first', async () => {
|
||||
const resolvers: Record<number, (b: Blob) => void> = {};
|
||||
mockFetch.mockImplementation(
|
||||
({ body }) =>
|
||||
new Promise((resolve) => {
|
||||
resolvers[body.offset] = resolve;
|
||||
}),
|
||||
);
|
||||
|
||||
const promise = runChunkedExport(runArgs({ totalRows: rowsForParts(3) }));
|
||||
// All 3 pages are in flight (concurrency 3); resolve in reverse order.
|
||||
await Promise.resolve();
|
||||
resolvers[100_000](new Blob(['h\nc\n']));
|
||||
resolvers[50_000](new Blob(['h\nb\n']));
|
||||
resolvers[0](new Blob(['h\na\n']));
|
||||
await promise;
|
||||
|
||||
await expect(savedFileText()).resolves.toBe('h\na\nb\nc\n');
|
||||
});
|
||||
|
||||
it('stops claiming pages once the server runs dry', async () => {
|
||||
// Count says 5 pages but the server only has data for page 0.
|
||||
mockFetch.mockImplementation(({ body }) =>
|
||||
Promise.resolve(body.offset === 0 ? new Blob(['h\na\n']) : new Blob([])),
|
||||
);
|
||||
|
||||
await runChunkedExport(runArgs({ totalRows: rowsForParts(5) }));
|
||||
|
||||
// Workers stop claiming once an empty part is observed — exact count is
|
||||
// timing-dependent, but it must never fetch all 5 pages.
|
||||
expect(mockFetch.mock.calls.length).toBeLessThan(5);
|
||||
await expect(savedFileText()).resolves.toBe('h\na\n');
|
||||
});
|
||||
|
||||
it('rejects on page failure, aborts in-flight siblings, saves nothing', async () => {
|
||||
const seenSignals: AbortSignal[] = [];
|
||||
mockFetch.mockImplementation(({ body, signal }) => {
|
||||
seenSignals.push(signal);
|
||||
return body.offset === 50_000
|
||||
? Promise.reject(new Error('boom'))
|
||||
: new Promise(() => {}); // siblings hang until aborted
|
||||
});
|
||||
|
||||
await expect(
|
||||
runChunkedExport(runArgs({ totalRows: rowsForParts(3) })),
|
||||
).rejects.toThrow('boom');
|
||||
|
||||
expect(seenSignals.every((s) => s.aborted)).toBe(true);
|
||||
expect(mockDownloadFile).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('propagates a user abort to the page fetches', async () => {
|
||||
const controller = new AbortController();
|
||||
mockFetch.mockImplementation(
|
||||
({ signal }) =>
|
||||
new Promise((_resolve, reject) => {
|
||||
signal.addEventListener('abort', () =>
|
||||
reject(new DOMException('Aborted', 'AbortError')),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
const promise = runChunkedExport(
|
||||
runArgs({ totalRows: rowsForParts(2), signal: controller.signal }),
|
||||
);
|
||||
await Promise.resolve();
|
||||
controller.abort();
|
||||
|
||||
await expect(promise).rejects.toThrow('Aborted');
|
||||
expect(mockDownloadFile).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('reports whole-number progress per completed part', async () => {
|
||||
mockFetch.mockImplementation(({ body }) =>
|
||||
Promise.resolve(new Blob([`h\nrow-${body.offset}\n`])),
|
||||
);
|
||||
const onProgress = jest.fn();
|
||||
|
||||
await runChunkedExport(runArgs({ totalRows: rowsForParts(3), onProgress }));
|
||||
|
||||
const reported = onProgress.mock.calls.map(([p]) => p);
|
||||
expect(reported).toHaveLength(3);
|
||||
expect(reported).toStrictEqual(expect.arrayContaining([33, 67, 100]));
|
||||
});
|
||||
});
|
||||
4
frontend/src/hooks/useExportData/constants.ts
Normal file
4
frontend/src/hooks/useExportData/constants.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export const EXPORT_PAGE_SIZE = 50_000;
|
||||
|
||||
/** Pages fetched in parallel.*/
|
||||
export const EXPORT_CONCURRENCY = 3;
|
||||
143
frontend/src/hooks/useExportData/runChunkedExport.ts
Normal file
143
frontend/src/hooks/useExportData/runChunkedExport.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
import { fetchExportData } from 'api/v1/download/downloadExportData';
|
||||
import { prepareQueryRangePayloadV5 } from 'api/v5/v5';
|
||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import {
|
||||
downloadFile,
|
||||
getTimestampedFileName,
|
||||
} from 'lib/exportData/downloadFile';
|
||||
import { stitchCsvParts, stitchJsonlParts } from 'lib/exportData/stitchParts';
|
||||
import { ExportFormat } from 'lib/exportData/types';
|
||||
import store from 'store';
|
||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { QueryRangePayloadV5 } from 'types/api/v5/queryRange';
|
||||
|
||||
import { EXPORT_CONCURRENCY, EXPORT_PAGE_SIZE } from './constants';
|
||||
|
||||
export interface ChunkedExportArgs {
|
||||
query: Query;
|
||||
timeRange: { start: number; end: number };
|
||||
// Total rows the query is expected to return; drives the page count.
|
||||
totalRows: number;
|
||||
fileNameBase: string;
|
||||
}
|
||||
|
||||
interface RunChunkedExportProps extends ChunkedExportArgs {
|
||||
format: ExportFormat;
|
||||
signal: AbortSignal;
|
||||
// 0–100 whole number: parts completed over total parts.
|
||||
onProgress: (progress: number) => void;
|
||||
}
|
||||
|
||||
const MIME_BY_FORMAT: Record<ExportFormat, string> = {
|
||||
[ExportFormat.Csv]: 'text/csv',
|
||||
[ExportFormat.Jsonl]: 'application/x-ndjson',
|
||||
};
|
||||
|
||||
/**
|
||||
* Chunked server export: fetches export_raw_data pages through a bounded
|
||||
* worker pool (EXPORT_CONCURRENCY wide — pages are independent since offsets
|
||||
* are precomputable), stitches the parts in page order client-side, and saves
|
||||
* a single file.
|
||||
*/
|
||||
export async function runChunkedExport({
|
||||
query,
|
||||
timeRange,
|
||||
totalRows,
|
||||
fileNameBase,
|
||||
format,
|
||||
signal,
|
||||
onProgress,
|
||||
}: RunChunkedExportProps): Promise<void> {
|
||||
const totalParts = Math.max(1, Math.ceil(totalRows / EXPORT_PAGE_SIZE));
|
||||
const workerCount = Math.min(Math.max(1, EXPORT_CONCURRENCY), totalParts);
|
||||
|
||||
// Internal controller so the first failed page (or a user cancel) stops the
|
||||
// whole fleet instead of letting siblings run to completion for nothing.
|
||||
const fleet = new AbortController();
|
||||
const onExternalAbort = (): void => fleet.abort();
|
||||
signal.addEventListener('abort', onExternalAbort);
|
||||
if (signal.aborted) {
|
||||
fleet.abort();
|
||||
}
|
||||
|
||||
const buildPagePayload = (page: number): QueryRangePayloadV5 => {
|
||||
const pageQuery: Query = {
|
||||
...query,
|
||||
builder: {
|
||||
...query.builder,
|
||||
queryData: query.builder.queryData.map((qd) => ({
|
||||
...qd,
|
||||
limit: EXPORT_PAGE_SIZE,
|
||||
pageSize: EXPORT_PAGE_SIZE,
|
||||
offset: page * EXPORT_PAGE_SIZE,
|
||||
})),
|
||||
},
|
||||
};
|
||||
|
||||
return prepareQueryRangePayloadV5({
|
||||
query: pageQuery,
|
||||
graphType: PANEL_TYPES.LIST,
|
||||
selectedTime: 'GLOBAL_TIME',
|
||||
// Read directly (not via hooks) — the absolute bounds below take
|
||||
// precedence over the global picker in the payload anyway.
|
||||
globalSelectedInterval: store.getState().globalTime.selectedTime,
|
||||
start: timeRange.start,
|
||||
end: timeRange.end,
|
||||
}).queryPayload;
|
||||
};
|
||||
|
||||
// Indexed by page so out-of-order completion can't scramble the stitch order.
|
||||
const parts = new Array<Blob | undefined>(totalParts);
|
||||
let nextPage = 0;
|
||||
let completedParts = 0;
|
||||
let serverRanDry = false;
|
||||
|
||||
const worker = async (): Promise<void> => {
|
||||
while (!serverRanDry) {
|
||||
const page = nextPage;
|
||||
nextPage += 1;
|
||||
if (page >= totalParts) {
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const part = await fetchExportData({
|
||||
format,
|
||||
body: buildPagePayload(page),
|
||||
signal: fleet.signal,
|
||||
});
|
||||
|
||||
// Empty part = the row count drifted and the server ran dry early;
|
||||
// stop claiming further pages (later in-flight pages are empty too).
|
||||
if (part.size === 0) {
|
||||
serverRanDry = true;
|
||||
return;
|
||||
}
|
||||
|
||||
parts[page] = part;
|
||||
completedParts += 1;
|
||||
onProgress(Math.round((completedParts / totalParts) * 100));
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
await Promise.all(Array.from({ length: workerCount }, () => worker()));
|
||||
} catch (error) {
|
||||
fleet.abort();
|
||||
throw error;
|
||||
} finally {
|
||||
signal.removeEventListener('abort', onExternalAbort);
|
||||
}
|
||||
|
||||
const orderedParts = parts.filter((part): part is Blob => Boolean(part));
|
||||
const stitched =
|
||||
format === ExportFormat.Csv
|
||||
? await stitchCsvParts(orderedParts)
|
||||
: await stitchJsonlParts(orderedParts);
|
||||
|
||||
downloadFile(
|
||||
stitched,
|
||||
getTimestampedFileName(fileNameBase, format),
|
||||
MIME_BY_FORMAT[format],
|
||||
);
|
||||
}
|
||||
100
frontend/src/lib/exportData/__tests__/stitchParts.test.ts
Normal file
100
frontend/src/lib/exportData/__tests__/stitchParts.test.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import 'tests/blob-polyfill';
|
||||
|
||||
import { stitchCsvParts, stitchJsonlParts } from '../stitchParts';
|
||||
|
||||
const blob = (content: string): Blob => new Blob([content]);
|
||||
|
||||
describe('stitchCsvParts', () => {
|
||||
it('keeps a single part as-is', async () => {
|
||||
const out = await stitchCsvParts([blob('h1,h2\na,b\n')]);
|
||||
await expect(out.text()).resolves.toBe('h1,h2\na,b\n');
|
||||
expect(out.type).toBe('text/csv');
|
||||
});
|
||||
|
||||
it('strips the header row from parts after the first', async () => {
|
||||
const out = await stitchCsvParts([
|
||||
blob('h1,h2\na,b\n'),
|
||||
blob('h1,h2\nc,d\n'),
|
||||
blob('h1,h2\ne,f\n'),
|
||||
]);
|
||||
await expect(out.text()).resolves.toBe('h1,h2\na,b\nc,d\ne,f\n');
|
||||
});
|
||||
|
||||
it('handles CRLF line endings (the \\r dies with the header)', async () => {
|
||||
const out = await stitchCsvParts([
|
||||
blob('h1,h2\r\na,b\r\n'),
|
||||
blob('h1,h2\r\nc,d\r\n'),
|
||||
]);
|
||||
await expect(out.text()).resolves.toBe('h1,h2\r\na,b\r\nc,d\r\n');
|
||||
});
|
||||
|
||||
it('inserts a newline at the seam when a part lacks a trailing one', async () => {
|
||||
const out = await stitchCsvParts([blob('h1,h2\na,b'), blob('h1,h2\nc,d')]);
|
||||
await expect(out.text()).resolves.toBe('h1,h2\na,b\nc,d\n');
|
||||
});
|
||||
|
||||
it('preserves multi-byte characters around the header boundary', async () => {
|
||||
const out = await stitchCsvParts([
|
||||
blob('höader,h2\naä,b\n'),
|
||||
blob('höader,h2\ncö,d\n'),
|
||||
]);
|
||||
await expect(out.text()).resolves.toBe('höader,h2\naä,b\ncö,d\n');
|
||||
});
|
||||
|
||||
it('strips headers longer than the initial 8KB sniff window', async () => {
|
||||
// Forces findFirstNewlineEnd through its window-doubling path.
|
||||
const hugeHeader = Array.from({ length: 1200 }, (_, i) => `column_${i}`).join(
|
||||
',',
|
||||
);
|
||||
expect(hugeHeader.length).toBeGreaterThan(8192);
|
||||
const out = await stitchCsvParts([
|
||||
blob(`${hugeHeader}\na,b\n`),
|
||||
blob(`${hugeHeader}\nc,d\n`),
|
||||
]);
|
||||
await expect(out.text()).resolves.toBe(`${hugeHeader}\na,b\nc,d\n`);
|
||||
});
|
||||
|
||||
it('skips empty and header-only parts', async () => {
|
||||
const out = await stitchCsvParts([
|
||||
blob('h1,h2\na,b\n'),
|
||||
blob(''),
|
||||
blob('h1,h2\n'),
|
||||
blob('h1,h2'),
|
||||
blob('h1,h2\nc,d\n'),
|
||||
]);
|
||||
await expect(out.text()).resolves.toBe('h1,h2\na,b\nc,d\n');
|
||||
});
|
||||
|
||||
it('returns an empty blob for no parts', async () => {
|
||||
const out = await stitchCsvParts([]);
|
||||
expect(out.size).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('stitchJsonlParts', () => {
|
||||
it('concatenates parts without stripping anything', async () => {
|
||||
const out = await stitchJsonlParts([
|
||||
blob('{"a":1}\n{"a":2}\n'),
|
||||
blob('{"a":3}\n'),
|
||||
]);
|
||||
await expect(out.text()).resolves.toBe('{"a":1}\n{"a":2}\n{"a":3}\n');
|
||||
expect(out.type).toBe('application/x-ndjson');
|
||||
});
|
||||
|
||||
it('guards the seam when a part lacks a trailing newline', async () => {
|
||||
const out = await stitchJsonlParts([blob('{"a":1}'), blob('{"a":2}')]);
|
||||
const text = await out.text();
|
||||
expect(text).toBe('{"a":1}\n{"a":2}\n');
|
||||
// Every line must stay independently parseable.
|
||||
const lines = text.trim().split('\n');
|
||||
expect(lines.map((line) => JSON.parse(line))).toStrictEqual([
|
||||
{ a: 1 },
|
||||
{ a: 2 },
|
||||
]);
|
||||
});
|
||||
|
||||
it('skips empty parts', async () => {
|
||||
const out = await stitchJsonlParts([blob(''), blob('{"a":1}\n'), blob('')]);
|
||||
await expect(out.text()).resolves.toBe('{"a":1}\n');
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
/** Triggers a browser download of in-memory string content as a file. */
|
||||
/** Triggers a browser download of in-memory content (string or Blob) as a file. */
|
||||
export function downloadFile(
|
||||
content: string,
|
||||
content: string | Blob,
|
||||
fileName: string,
|
||||
mime: string,
|
||||
): void {
|
||||
|
||||
85
frontend/src/lib/exportData/stitchParts.ts
Normal file
85
frontend/src/lib/exportData/stitchParts.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Stitches sequentially-fetched export parts (Blobs) into one downloadable
|
||||
* Blob. Pure blob surgery — parts are never parsed and `Blob.slice`/`new Blob`
|
||||
* are zero-copy, so nothing here scales with the data size except the final
|
||||
* browser-managed blob itself.
|
||||
*/
|
||||
|
||||
const HEADER_SNIFF_BYTES = 8192;
|
||||
const NEWLINE_BYTE = 0x0a;
|
||||
|
||||
/** Byte offset just past the first newline, or -1 when the blob has none. */
|
||||
async function findFirstNewlineEnd(blob: Blob): Promise<number> {
|
||||
let sniffBytes = HEADER_SNIFF_BYTES;
|
||||
for (;;) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const bytes = new Uint8Array(await blob.slice(0, sniffBytes).arrayBuffer());
|
||||
const newlineIdx = bytes.indexOf(NEWLINE_BYTE);
|
||||
if (newlineIdx !== -1) {
|
||||
return newlineIdx + 1;
|
||||
}
|
||||
if (sniffBytes >= blob.size) {
|
||||
return -1;
|
||||
}
|
||||
sniffBytes *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
async function endsWithNewline(blob: Blob): Promise<boolean> {
|
||||
const lastByte = new Uint8Array(await blob.slice(blob.size - 1).arrayBuffer());
|
||||
return lastByte[0] === NEWLINE_BYTE;
|
||||
}
|
||||
|
||||
async function stitchParts(
|
||||
parts: Blob[],
|
||||
{
|
||||
stripHeaderAfterFirst,
|
||||
mime,
|
||||
}: { stripHeaderAfterFirst: boolean; mime: string },
|
||||
): Promise<Blob> {
|
||||
const pieces: (Blob | string)[] = [];
|
||||
|
||||
for (let index = 0; index < parts.length; index += 1) {
|
||||
let piece = parts[index];
|
||||
|
||||
if (stripHeaderAfterFirst && index > 0) {
|
||||
// Every part re-sends the header row; drop it on parts 2..N. Byte-level
|
||||
// search (not text) so multi-byte characters can't skew the offset.
|
||||
// ASSUMPTION: the first newline byte ends the header row — i.e. no
|
||||
// column name contains an embedded (RFC 4180 quoted) newline. Header
|
||||
// cells are telemetry field names, which can't carry newlines; quoted
|
||||
// newlines in DATA rows are fine (we only search from byte 0).
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const headerEnd = await findFirstNewlineEnd(piece);
|
||||
// A part without any newline is header-only — nothing to keep.
|
||||
piece = headerEnd === -1 ? piece.slice(piece.size) : piece.slice(headerEnd);
|
||||
}
|
||||
|
||||
if (piece.size === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pieces.push(piece);
|
||||
// Guard the seam: without a trailing newline the next part's first row
|
||||
// would concatenate onto this part's last row.
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
if (!(await endsWithNewline(piece))) {
|
||||
pieces.push('\n');
|
||||
}
|
||||
}
|
||||
|
||||
return new Blob(pieces, { type: mime });
|
||||
}
|
||||
|
||||
/** Combines CSV parts: part 1 keeps its header, parts 2..N are decapitated. */
|
||||
export async function stitchCsvParts(parts: Blob[]): Promise<Blob> {
|
||||
return stitchParts(parts, { stripHeaderAfterFirst: true, mime: 'text/csv' });
|
||||
}
|
||||
|
||||
/** Combines JSONL parts: plain concatenation with a newline guard per seam. */
|
||||
export async function stitchJsonlParts(parts: Blob[]): Promise<Blob> {
|
||||
return stitchParts(parts, {
|
||||
stripHeaderAfterFirst: false,
|
||||
mime: 'application/x-ndjson',
|
||||
});
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { Info } from '@signozhq/icons';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { DashboardtypesDynamicVariableSignalDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import cx from 'classnames';
|
||||
// eslint-disable-next-line signoz/no-antd-components -- fixed-option signal picker
|
||||
import { Select } from 'antd';
|
||||
@@ -14,17 +15,16 @@ import { isRetryableError } from 'utils/errorUtils';
|
||||
import {
|
||||
DYNAMIC_SIGNAL_LABEL,
|
||||
DYNAMIC_SIGNALS,
|
||||
type DynamicSignalOption,
|
||||
signalForApi,
|
||||
} from '../variableFormModel';
|
||||
import styles from './VariableForm.module.scss';
|
||||
|
||||
interface DynamicVariableFieldsProps {
|
||||
attribute: string;
|
||||
signal: DynamicSignalOption;
|
||||
signal: DashboardtypesDynamicVariableSignalDTO;
|
||||
onChange: (patch: {
|
||||
dynamicAttribute?: string;
|
||||
dynamicSignal?: DynamicSignalOption;
|
||||
dynamicSignal?: DashboardtypesDynamicVariableSignalDTO;
|
||||
}) => void;
|
||||
onPreview: (values: (string | number)[]) => void;
|
||||
/** Inline error shown under the attribute field (e.g. duplicate attribute). */
|
||||
@@ -117,7 +117,9 @@ function DynamicVariableFields({
|
||||
value: s,
|
||||
}))}
|
||||
onChange={(value): void =>
|
||||
onChange({ dynamicSignal: value as DynamicSignalOption })
|
||||
onChange({
|
||||
dynamicSignal: value as DashboardtypesDynamicVariableSignalDTO,
|
||||
})
|
||||
}
|
||||
data-testid="variable-signal-select"
|
||||
/>
|
||||
|
||||
@@ -13,11 +13,7 @@ import type {
|
||||
} from 'api/generated/services/sigNoz.schemas';
|
||||
|
||||
import {
|
||||
DYNAMIC_SIGNAL_ALL,
|
||||
DYNAMIC_SIGNALS,
|
||||
type DynamicSignalOption,
|
||||
emptyVariableFormModel,
|
||||
signalForApi,
|
||||
VARIABLE_SORT_DISABLED,
|
||||
type VariableFormModel,
|
||||
} from './variableFormModel';
|
||||
@@ -69,12 +65,8 @@ export function dtoToFormModel(
|
||||
...listCommon,
|
||||
type: 'DYNAMIC',
|
||||
dynamicAttribute: plugin.spec.name ?? '',
|
||||
// Unrecognized/empty signal → "all telemetry", so the source always shows.
|
||||
dynamicSignal: DYNAMIC_SIGNALS.includes(
|
||||
plugin.spec.signal as DynamicSignalOption,
|
||||
)
|
||||
? (plugin.spec.signal as DynamicSignalOption)
|
||||
: DYNAMIC_SIGNAL_ALL,
|
||||
// signal is a required wire field (`all` = every telemetry signal), used as-is.
|
||||
dynamicSignal: plugin.spec.signal,
|
||||
};
|
||||
}
|
||||
// Default to Query (also covers a query plugin or a missing/unknown plugin).
|
||||
@@ -102,7 +94,7 @@ function buildPlugin(
|
||||
kind: DynamicPluginKind['signoz/DynamicVariable'],
|
||||
spec: {
|
||||
name: model.dynamicAttribute,
|
||||
signal: signalForApi(model.dynamicSignal),
|
||||
signal: model.dynamicSignal,
|
||||
},
|
||||
};
|
||||
case 'QUERY':
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
DashboardtypesDynamicVariableSignalDTO,
|
||||
DashboardtypesListVariableSpecSortDTO,
|
||||
TelemetrytypesSignalDTO,
|
||||
} from 'api/generated/services/sigNoz.schemas';
|
||||
import type { DashboardtypesVariableDefaultValueDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import { sortBy } from 'lodash-es';
|
||||
@@ -23,23 +23,6 @@ export const VARIABLE_TYPE_EVENT_LABEL: Record<VariableType, string> = {
|
||||
DYNAMIC: 'dynamic',
|
||||
};
|
||||
|
||||
/** Telemetry signal — the generated enum (traces / logs / metrics). */
|
||||
// A query/variable signal is only logs/traces/metrics. TelemetrytypesSignalDTO
|
||||
// also carries the empty "any" value used on field keys, which is not a valid
|
||||
// query/variable signal, so exclude it here.
|
||||
export type TelemetrySignal =
|
||||
| TelemetrytypesSignalDTO.logs
|
||||
| TelemetrytypesSignalDTO.traces
|
||||
| TelemetrytypesSignalDTO.metrics;
|
||||
|
||||
/**
|
||||
* Signal selected in the dynamic-variable editor. `'all'` is UI-only (the
|
||||
* generated `TelemetrytypesSignalDTO` has no "all") — it searches across every
|
||||
* signal and maps to an omitted `signal` on the wire (see {@link signalForApi}).
|
||||
*/
|
||||
export const DYNAMIC_SIGNAL_ALL = 'all' as const;
|
||||
export type DynamicSignalOption = TelemetrySignal | typeof DYNAMIC_SIGNAL_ALL;
|
||||
|
||||
/**
|
||||
* Sort order for list-variable values, keyed by the generated wire enum so the
|
||||
* form model and the DTO `sort` field share one source of truth. The friendly
|
||||
@@ -81,25 +64,38 @@ export const VARIABLE_SORT_LABEL: Record<VariableSort, string> = {
|
||||
[VARIABLE_SORT.CI_DESC]: 'Alphabetical, case-insensitive (descending)',
|
||||
};
|
||||
|
||||
export const DYNAMIC_SIGNALS: DynamicSignalOption[] = [
|
||||
DYNAMIC_SIGNAL_ALL,
|
||||
TelemetrytypesSignalDTO.traces,
|
||||
TelemetrytypesSignalDTO.logs,
|
||||
TelemetrytypesSignalDTO.metrics,
|
||||
export const DYNAMIC_SIGNALS: DashboardtypesDynamicVariableSignalDTO[] = [
|
||||
DashboardtypesDynamicVariableSignalDTO.all,
|
||||
DashboardtypesDynamicVariableSignalDTO.traces,
|
||||
DashboardtypesDynamicVariableSignalDTO.logs,
|
||||
DashboardtypesDynamicVariableSignalDTO.metrics,
|
||||
];
|
||||
|
||||
export const DYNAMIC_SIGNAL_LABEL: Record<DynamicSignalOption, string> = {
|
||||
[DYNAMIC_SIGNAL_ALL]: 'All telemetry',
|
||||
[TelemetrytypesSignalDTO.traces]: 'Traces',
|
||||
[TelemetrytypesSignalDTO.logs]: 'Logs',
|
||||
[TelemetrytypesSignalDTO.metrics]: 'Metrics',
|
||||
export const DYNAMIC_SIGNAL_LABEL: Record<
|
||||
DashboardtypesDynamicVariableSignalDTO,
|
||||
string
|
||||
> = {
|
||||
[DashboardtypesDynamicVariableSignalDTO.all]: 'All telemetry',
|
||||
[DashboardtypesDynamicVariableSignalDTO.traces]: 'Traces',
|
||||
[DashboardtypesDynamicVariableSignalDTO.logs]: 'Logs',
|
||||
[DashboardtypesDynamicVariableSignalDTO.metrics]: 'Metrics',
|
||||
};
|
||||
|
||||
/** Maps the editor's signal selection to the wire value (`'all'` → omitted). */
|
||||
/**
|
||||
* Field-keys/values API param. The `all` signal is omitted (that endpoint only
|
||||
* accepts a concrete signal), everything else passes through.
|
||||
*/
|
||||
export function signalForApi(
|
||||
signal: DynamicSignalOption,
|
||||
): TelemetrySignal | undefined {
|
||||
return signal === DYNAMIC_SIGNAL_ALL ? undefined : signal;
|
||||
signal: DashboardtypesDynamicVariableSignalDTO,
|
||||
):
|
||||
| Exclude<
|
||||
DashboardtypesDynamicVariableSignalDTO,
|
||||
DashboardtypesDynamicVariableSignalDTO.all
|
||||
>
|
||||
| undefined {
|
||||
return signal === DashboardtypesDynamicVariableSignalDTO.all
|
||||
? undefined
|
||||
: signal;
|
||||
}
|
||||
|
||||
type SortableValues = (string | number | boolean)[];
|
||||
@@ -144,7 +140,7 @@ export interface VariableFormModel {
|
||||
textValue: string; // TEXT
|
||||
textConstant: boolean; // TEXT
|
||||
dynamicAttribute: string; // DYNAMIC — the telemetry field name
|
||||
dynamicSignal: DynamicSignalOption; // DYNAMIC — the telemetry signal
|
||||
dynamicSignal: DashboardtypesDynamicVariableSignalDTO; // DYNAMIC — the telemetry signal (`all` = every signal)
|
||||
|
||||
/**
|
||||
* Runtime-selected default, not editable in the management tab yet; carried
|
||||
@@ -166,6 +162,6 @@ export function emptyVariableFormModel(): VariableFormModel {
|
||||
textValue: '',
|
||||
textConstant: false,
|
||||
dynamicAttribute: '',
|
||||
dynamicSignal: DYNAMIC_SIGNAL_ALL,
|
||||
dynamicSignal: DashboardtypesDynamicVariableSignalDTO.all,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -17,8 +17,6 @@ const SIGNAL_LABEL: Record<TelemetrytypesSignalDTO, string> = {
|
||||
[TelemetrytypesSignalDTO.logs]: 'logs',
|
||||
[TelemetrytypesSignalDTO.traces]: 'traces',
|
||||
[TelemetrytypesSignalDTO.metrics]: 'metrics',
|
||||
// The empty "any" signal only appears on field keys, never on a panel query;
|
||||
// mapped for exhaustiveness.
|
||||
[TelemetrytypesSignalDTO['']]: '',
|
||||
};
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ export const SECTION_REGISTRY: {
|
||||
[SectionKind.ContextLinks]: {
|
||||
Component: ContextLinksSection,
|
||||
// Panel-level slice (spec.links), not under the plugin spec — no cast needed.
|
||||
get: (spec): DashboardtypesLinkDTO[] | undefined => spec.links ?? undefined,
|
||||
get: (spec): DashboardtypesLinkDTO[] => spec.links,
|
||||
update: (spec, links): PanelSpec => ({ ...spec, links }),
|
||||
},
|
||||
// One editor for every threshold variant (label / comparison / table); the kind's
|
||||
|
||||
@@ -49,6 +49,14 @@ describe('newPanelRoute', () => {
|
||||
return { path, params: new URLSearchParams(search) };
|
||||
};
|
||||
|
||||
// Mirrors useGetCompositeQueryParam: it decodes the param twice.
|
||||
const readCompositeQuery = (params: URLSearchParams): unknown =>
|
||||
JSON.parse(
|
||||
decodeURIComponent(
|
||||
(params.get('compositeQuery') as string).replace(/\+/g, ' '),
|
||||
),
|
||||
);
|
||||
|
||||
it.each([
|
||||
[PANEL_TYPES.TIME_SERIES, 'signoz/TimeSeriesPanel'],
|
||||
[PANEL_TYPES.TABLE, 'signoz/TablePanel'],
|
||||
@@ -67,16 +75,34 @@ describe('newPanelRoute', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('carries the query as a decodable compositeQuery param', () => {
|
||||
it('carries the query as a compositeQuery param the reader can decode', () => {
|
||||
const link = buildExportPanelLink({
|
||||
dashboardId: 'dash-1',
|
||||
panelType: PANEL_TYPES.TIME_SERIES,
|
||||
query,
|
||||
});
|
||||
const { params } = parseLink(link);
|
||||
expect(JSON.parse(params.get('compositeQuery') as string)).toStrictEqual(
|
||||
query,
|
||||
);
|
||||
expect(readCompositeQuery(params)).toStrictEqual(query);
|
||||
});
|
||||
|
||||
// Regression: a bare `%`/`+` must survive the reader's double-decode.
|
||||
it('round-trips a filter expression containing % and + literals', () => {
|
||||
const queryWithLiterals = {
|
||||
id: 'q1',
|
||||
queryType: 'builder',
|
||||
builder: {
|
||||
queryData: [
|
||||
{ filter: { expression: "severity_text ILIKE 'Inf%' AND path = 'a+b'" } },
|
||||
],
|
||||
},
|
||||
} as unknown as Query;
|
||||
const link = buildExportPanelLink({
|
||||
dashboardId: 'dash-1',
|
||||
panelType: PANEL_TYPES.LIST,
|
||||
query: queryWithLiterals,
|
||||
});
|
||||
const { params } = parseLink(link);
|
||||
expect(readCompositeQuery(params)).toStrictEqual(queryWithLiterals);
|
||||
});
|
||||
|
||||
it('returns null for a panel type with no V2 kind', () => {
|
||||
|
||||
@@ -45,9 +45,11 @@ export function parseNewPanelKind(
|
||||
|
||||
/**
|
||||
* New-panel editor link that exports an explorer query into a V2 dashboard. Carries the
|
||||
* raw `Query` as `compositeQuery` encoded as the V1 link so `useGetCompositeQueryParam`
|
||||
* reads it identically (conversion happens in the editor). `null` when the panel type has
|
||||
* no V2 kind, so the caller skips the export instead of landing on an unrelated kind.
|
||||
* raw `Query` as `compositeQuery` (conversion happens in the editor). `null` when the panel
|
||||
* type has no V2 kind, so the caller skips the export instead of landing on an unrelated kind.
|
||||
*
|
||||
* Double-encoded on purpose: `useGetCompositeQueryParam` decodes twice, so a single encode
|
||||
* would let a bare `%`/`+` (e.g. `ILIKE 'Inf%'`) break its second decode and drop the query.
|
||||
*/
|
||||
export function buildExportPanelLink({
|
||||
dashboardId,
|
||||
@@ -68,7 +70,7 @@ export function buildExportPanelLink({
|
||||
});
|
||||
return `${path}${newPanelSearch(kind)}&${
|
||||
QueryParams.compositeQuery
|
||||
}=${encodeURIComponent(JSON.stringify(query))}`;
|
||||
}=${encodeURIComponent(encodeURIComponent(JSON.stringify(query)))}`;
|
||||
}
|
||||
|
||||
/** Target section index for a new panel, or undefined when unset/invalid. */
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import type { DashboardtypesQueryDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
|
||||
import { countEnabledQueries } from '../countEnabledQueries';
|
||||
|
||||
function compositeQuery(
|
||||
envelopes: { type: string; disabled?: boolean }[],
|
||||
): DashboardtypesQueryDTO {
|
||||
return {
|
||||
spec: {
|
||||
plugin: {
|
||||
kind: 'signoz/CompositeQuery',
|
||||
spec: {
|
||||
queries: envelopes.map(({ type, disabled }) => ({
|
||||
type,
|
||||
spec: { disabled },
|
||||
})),
|
||||
},
|
||||
},
|
||||
},
|
||||
} as unknown as DashboardtypesQueryDTO;
|
||||
}
|
||||
|
||||
function bareBuilderQuery(disabled?: boolean): DashboardtypesQueryDTO {
|
||||
return {
|
||||
spec: {
|
||||
plugin: { kind: 'signoz/BuilderQuery', spec: { signal: 'logs', disabled } },
|
||||
},
|
||||
} as unknown as DashboardtypesQueryDTO;
|
||||
}
|
||||
|
||||
describe('countEnabledQueries', () => {
|
||||
it('returns 0 when there are no queries', () => {
|
||||
expect(countEnabledQueries([])).toBe(0);
|
||||
});
|
||||
|
||||
it('counts every enabled envelope inside the composite wrapper', () => {
|
||||
expect(
|
||||
countEnabledQueries([
|
||||
compositeQuery([{ type: 'builder_query' }, { type: 'builder_query' }]),
|
||||
]),
|
||||
).toBe(2);
|
||||
});
|
||||
|
||||
it('does not count disabled envelopes', () => {
|
||||
expect(
|
||||
countEnabledQueries([
|
||||
compositeQuery([
|
||||
{ type: 'builder_query' },
|
||||
{ type: 'builder_query', disabled: true },
|
||||
]),
|
||||
]),
|
||||
).toBe(1);
|
||||
});
|
||||
|
||||
it('counts formula envelopes alongside builder queries', () => {
|
||||
expect(
|
||||
countEnabledQueries([
|
||||
compositeQuery([
|
||||
{ type: 'builder_query' },
|
||||
{ type: 'builder_query' },
|
||||
{ type: 'builder_formula' },
|
||||
]),
|
||||
]),
|
||||
).toBe(3);
|
||||
});
|
||||
|
||||
it('treats an absent disabled flag as enabled', () => {
|
||||
expect(
|
||||
countEnabledQueries([compositeQuery([{ type: 'builder_query' }])]),
|
||||
).toBe(1);
|
||||
});
|
||||
|
||||
it('unwraps a bare builder query (List panel shape)', () => {
|
||||
expect(countEnabledQueries([bareBuilderQuery()])).toBe(1);
|
||||
});
|
||||
|
||||
it('does not count a disabled bare builder query', () => {
|
||||
expect(countEnabledQueries([bareBuilderQuery(true)])).toBe(0);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
import type { DashboardtypesQueryDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import { toQueryEnvelopes } from 'pages/DashboardPageV2/DashboardContainer/queryV5/buildQueryRangeRequest';
|
||||
|
||||
/** Counts enabled queries, unwrapping the single `signoz/CompositeQuery` wrapper. */
|
||||
export function countEnabledQueries(queries: DashboardtypesQueryDTO[]): number {
|
||||
return toQueryEnvelopes(queries).filter((envelope) => !envelope.spec?.disabled)
|
||||
.length;
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
import { TelemetrytypesSignalDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import {
|
||||
DashboardtypesDynamicVariableSignalDTO,
|
||||
TelemetrytypesSignalDTO,
|
||||
} from 'api/generated/services/sigNoz.schemas';
|
||||
import type { BuilderQuery } from 'types/api/v5/queryRange';
|
||||
|
||||
/**
|
||||
@@ -17,3 +20,23 @@ export function resolveDrilldownSignal(
|
||||
return TelemetrytypesSignalDTO.metrics;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a clicked query's telemetry signal to a dynamic-variable signal (used
|
||||
* when a drilldown seeds a new variable). Concrete signals map 1:1; an unset
|
||||
* signal (no active drilldown) falls back to `all`.
|
||||
*/
|
||||
export function dynamicSignalFromQuerySignal(
|
||||
signal?: TelemetrytypesSignalDTO,
|
||||
): DashboardtypesDynamicVariableSignalDTO {
|
||||
switch (signal) {
|
||||
case TelemetrytypesSignalDTO.traces:
|
||||
return DashboardtypesDynamicVariableSignalDTO.traces;
|
||||
case TelemetrytypesSignalDTO.logs:
|
||||
return DashboardtypesDynamicVariableSignalDTO.logs;
|
||||
case TelemetrytypesSignalDTO.metrics:
|
||||
return DashboardtypesDynamicVariableSignalDTO.metrics;
|
||||
default:
|
||||
return DashboardtypesDynamicVariableSignalDTO.all;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import PanelHeaderSearch from './PanelHeaderSearch';
|
||||
import PanelStatusPopover from '../PanelStatus/PanelStatusPopover';
|
||||
import {
|
||||
panelStatusFromError,
|
||||
panelStatusFromMultipleEnabledQueries,
|
||||
panelStatusFromWarning,
|
||||
} from '../PanelStatus/utils';
|
||||
import styles from './PanelHeader.module.scss';
|
||||
@@ -74,11 +75,24 @@ function PanelHeader({
|
||||
[warning],
|
||||
);
|
||||
|
||||
// Client-derived: warn a Number panel that has more than one enabled query (#9512).
|
||||
const multiQueryWarningDetail = useMemo(
|
||||
() => panelStatusFromMultipleEnabledQueries(panel),
|
||||
[panel],
|
||||
);
|
||||
|
||||
/**
|
||||
* Hide the entire header when there's no title, description, or status to show,
|
||||
* and the actions menu is suppressed (editor preview).
|
||||
*/
|
||||
if (!name && !description && !errorDetail && !warningDetail && hideActions) {
|
||||
if (
|
||||
!name &&
|
||||
!description &&
|
||||
!errorDetail &&
|
||||
!warningDetail &&
|
||||
!multiQueryWarningDetail &&
|
||||
hideActions
|
||||
) {
|
||||
return <Fragment />;
|
||||
}
|
||||
|
||||
@@ -124,6 +138,13 @@ function PanelHeader({
|
||||
{warningDetail && (
|
||||
<PanelStatusPopover variant="warning" detail={warningDetail} />
|
||||
)}
|
||||
{multiQueryWarningDetail && (
|
||||
<PanelStatusPopover
|
||||
variant="warning"
|
||||
detail={multiQueryWarningDetail}
|
||||
testId="panel-status-config-warning"
|
||||
/>
|
||||
)}
|
||||
{/* Renders nothing when no action survives its gates (kind/role/context). */}
|
||||
{!hideActions && (
|
||||
<PanelActionsMenu
|
||||
|
||||
@@ -17,6 +17,8 @@ const VARIANT_CONFIG: Record<
|
||||
interface PanelStatusPopoverProps {
|
||||
variant: PanelStatusVariant;
|
||||
detail: PanelStatusDetail;
|
||||
/** Overrides the trigger's test id; defaults to `panel-status-<variant>`. */
|
||||
testId?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -26,6 +28,7 @@ interface PanelStatusPopoverProps {
|
||||
function PanelStatusPopover({
|
||||
variant,
|
||||
detail,
|
||||
testId,
|
||||
}: PanelStatusPopoverProps): JSX.Element {
|
||||
const { color, ariaLabel } = VARIANT_CONFIG[variant];
|
||||
const Icon = variant === 'error' ? CircleX : TriangleAlert;
|
||||
@@ -41,7 +44,7 @@ function PanelStatusPopover({
|
||||
<span
|
||||
className={styles.trigger}
|
||||
aria-label={ariaLabel}
|
||||
data-testid={`panel-status-${variant}`}
|
||||
data-testid={testId ?? `panel-status-${variant}`}
|
||||
>
|
||||
<Icon size={16} color={color} />
|
||||
</span>
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
import type { RenderErrorResponseDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import type {
|
||||
DashboardtypesPanelDTO,
|
||||
Querybuildertypesv5QueryWarnDataDTO as WarningDTO,
|
||||
RenderErrorResponseDTO,
|
||||
} from 'api/generated/services/sigNoz.schemas';
|
||||
import type { AxiosError } from 'axios';
|
||||
import type { Querybuildertypesv5QueryWarnDataDTO as WarningDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import { StatusCodes } from 'http-status-codes';
|
||||
|
||||
import { panelStatusFromError, panelStatusFromWarning } from '../utils';
|
||||
import {
|
||||
panelStatusFromError,
|
||||
panelStatusFromMultipleEnabledQueries,
|
||||
panelStatusFromWarning,
|
||||
} from '../utils';
|
||||
|
||||
// The query layer rejects with the raw AxiosError from the generated client
|
||||
// (it is not pre-converted to APIError), so the tests mirror that wire shape.
|
||||
@@ -87,3 +94,62 @@ describe('panelStatusFromWarning', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function panel(
|
||||
kind: string,
|
||||
envelopes: { disabled?: boolean }[],
|
||||
): DashboardtypesPanelDTO {
|
||||
return {
|
||||
spec: {
|
||||
plugin: { kind, spec: {} },
|
||||
queries: [
|
||||
{
|
||||
spec: {
|
||||
plugin: {
|
||||
kind: 'signoz/CompositeQuery',
|
||||
spec: {
|
||||
queries: envelopes.map(({ disabled }) => ({
|
||||
type: 'builder_query',
|
||||
spec: { disabled },
|
||||
})),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
} as unknown as DashboardtypesPanelDTO;
|
||||
}
|
||||
|
||||
describe('panelStatusFromMultipleEnabledQueries', () => {
|
||||
it('warns when a Number panel has more than one enabled query', () => {
|
||||
const detail = panelStatusFromMultipleEnabledQueries(
|
||||
panel('signoz/NumberPanel', [{}, {}]),
|
||||
);
|
||||
expect(detail).not.toBeNull();
|
||||
expect(detail?.message).toMatch(/single value/i);
|
||||
expect(detail?.messages).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('counts only enabled queries (a disabled second query is fine)', () => {
|
||||
expect(
|
||||
panelStatusFromMultipleEnabledQueries(
|
||||
panel('signoz/NumberPanel', [{}, { disabled: true }]),
|
||||
),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('does not warn when a Number panel has a single enabled query', () => {
|
||||
expect(
|
||||
panelStatusFromMultipleEnabledQueries(panel('signoz/NumberPanel', [{}])),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('does not warn for other panel kinds even with multiple enabled queries', () => {
|
||||
expect(
|
||||
panelStatusFromMultipleEnabledQueries(
|
||||
panel('signoz/TimeSeriesPanel', [{}, {}]),
|
||||
),
|
||||
).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { convertToApiError } from 'api/ErrorResponseHandlerForGeneratedAPIs';
|
||||
import type { RenderErrorResponseDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import type {
|
||||
DashboardtypesPanelDTO,
|
||||
Querybuildertypesv5QueryWarnDataDTO as WarningDTO,
|
||||
RenderErrorResponseDTO,
|
||||
} from 'api/generated/services/sigNoz.schemas';
|
||||
import type { AxiosError } from 'axios';
|
||||
import type { Querybuildertypesv5QueryWarnDataDTO as WarningDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import { countEnabledQueries } from 'pages/DashboardPageV2/DashboardContainer/Panels/utils/countEnabledQueries';
|
||||
|
||||
import type { PanelStatusDetail } from './types';
|
||||
|
||||
@@ -52,3 +56,25 @@ export function panelStatusFromWarning(
|
||||
.filter((message): message is string => Boolean(message)),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A Number panel renders only the first query's value, so more than one enabled
|
||||
* query silently hides the rest. Warns for that case; null otherwise.
|
||||
*/
|
||||
export function panelStatusFromMultipleEnabledQueries(
|
||||
panel: DashboardtypesPanelDTO,
|
||||
): PanelStatusDetail | null {
|
||||
if (panel.spec.plugin.kind !== 'signoz/NumberPanel') {
|
||||
return null;
|
||||
}
|
||||
if (countEnabledQueries(panel.spec.queries) <= 1) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
message:
|
||||
'This panel shows a single value, but more than one query is enabled.',
|
||||
messages: [
|
||||
"Disable the queries you don't want to display, keeping only the one whose value you want to show.",
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -41,6 +41,40 @@ function makePanel(overrides?: {
|
||||
} as unknown as DashboardtypesPanelDTO;
|
||||
}
|
||||
|
||||
// Blank name so the editor-preview guard test relies on the warning alone.
|
||||
function makePanelWithQueries(
|
||||
kind: string,
|
||||
enabled: number,
|
||||
disabled = 0,
|
||||
): DashboardtypesPanelDTO {
|
||||
const envelope = (isDisabled: boolean): unknown => ({
|
||||
type: 'builder_query',
|
||||
spec: { disabled: isDisabled },
|
||||
});
|
||||
return {
|
||||
kind: 'Panel',
|
||||
spec: {
|
||||
display: { name: '' },
|
||||
plugin: { kind, spec: {} },
|
||||
queries: [
|
||||
{
|
||||
spec: {
|
||||
plugin: {
|
||||
kind: 'signoz/CompositeQuery',
|
||||
spec: {
|
||||
queries: [
|
||||
...Array.from({ length: enabled }, () => envelope(false)),
|
||||
...Array.from({ length: disabled }, () => envelope(true)),
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
} as unknown as DashboardtypesPanelDTO;
|
||||
}
|
||||
|
||||
const baseProps = {
|
||||
panel: makePanel(),
|
||||
panelId: 'panel-1',
|
||||
@@ -101,6 +135,53 @@ describe('PanelHeader status indicators', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('PanelHeader multi-query config warning (issue #9512)', () => {
|
||||
it('warns when a Number panel has more than one enabled query', () => {
|
||||
renderWithProvider(
|
||||
<PanelHeader
|
||||
{...baseProps}
|
||||
panel={makePanelWithQueries('signoz/NumberPanel', 2)}
|
||||
/>,
|
||||
);
|
||||
expect(screen.getByTestId('panel-status-config-warning')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not warn when only one query is enabled (others disabled)', () => {
|
||||
renderWithProvider(
|
||||
<PanelHeader
|
||||
{...baseProps}
|
||||
panel={makePanelWithQueries('signoz/NumberPanel', 1, 2)}
|
||||
/>,
|
||||
);
|
||||
expect(
|
||||
screen.queryByTestId('panel-status-config-warning'),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not warn for non-Number panels with multiple enabled queries', () => {
|
||||
renderWithProvider(
|
||||
<PanelHeader
|
||||
{...baseProps}
|
||||
panel={makePanelWithQueries('signoz/TimeSeriesPanel', 3)}
|
||||
/>,
|
||||
);
|
||||
expect(
|
||||
screen.queryByTestId('panel-status-config-warning'),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows the warning in the editor preview (hideActions, no title)', () => {
|
||||
renderWithProvider(
|
||||
<PanelHeader
|
||||
{...baseProps}
|
||||
panel={makePanelWithQueries('signoz/NumberPanel', 2)}
|
||||
hideActions
|
||||
/>,
|
||||
);
|
||||
expect(screen.getByTestId('panel-status-config-warning')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('PanelHeader search', () => {
|
||||
it('renders no search affordance when the panel is not searchable', () => {
|
||||
renderWithProvider(<PanelHeader {...baseProps} />);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { render, renderHook, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { TelemetrytypesSignalDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import { DashboardtypesDynamicVariableSignalDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import type { FilterData } from 'container/QueryTable/Drilldown/drilldownUtils';
|
||||
|
||||
import DrilldownDashboardVariablesMenu from '../DrilldownMenu/DrilldownDashboardVariablesMenu';
|
||||
@@ -63,7 +63,6 @@ jest.mock(
|
||||
'pages/DashboardPageV2/DashboardContainer/DashboardSettings/Variables/variableFormModel',
|
||||
() => ({
|
||||
emptyVariableFormModel: (): unknown => ({}),
|
||||
DYNAMIC_SIGNAL_ALL: 'all',
|
||||
}),
|
||||
);
|
||||
jest.mock('components/OverlayScrollbar/OverlayScrollbar', () => ({
|
||||
@@ -84,7 +83,7 @@ function renderItems(): void {
|
||||
const { result } = renderHook(() =>
|
||||
useDrilldownDashboardVariables({
|
||||
filters,
|
||||
signal: TelemetrytypesSignalDTO.metrics,
|
||||
signal: DashboardtypesDynamicVariableSignalDTO.metrics,
|
||||
onClose: jest.fn(),
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -19,6 +19,7 @@ import { buildAggregateData } from 'pages/DashboardPageV2/DashboardContainer/Pan
|
||||
import { getBuilderQueries } from 'pages/DashboardPageV2/DashboardContainer/Panels/utils/getBuilderQueries';
|
||||
import { getPanelQueryType } from 'pages/DashboardPageV2/DashboardContainer/Panels/utils/getPanelQueryType';
|
||||
import { fromPerses } from 'pages/DashboardPageV2/DashboardContainer/queryV5/persesQueryAdapters';
|
||||
import { dynamicSignalFromQuerySignal } from 'pages/DashboardPageV2/DashboardContainer/Panels/utils/drilldown/signal';
|
||||
import { DashboardDetailEvents } from 'pages/DashboardPageV2/constants/events';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
|
||||
@@ -163,7 +164,7 @@ export function useDrilldown(
|
||||
|
||||
const dashboardVariables = useDrilldownDashboardVariables({
|
||||
filters: context?.filters ?? EMPTY_FILTERS,
|
||||
signal: context?.signal,
|
||||
signal: dynamicSignalFromQuerySignal(context?.signal),
|
||||
onClose: handleClose,
|
||||
});
|
||||
|
||||
@@ -221,7 +222,7 @@ export function useDrilldown(
|
||||
context={context}
|
||||
query={v1Query}
|
||||
isResolving={isResolving}
|
||||
links={panel.spec.links ?? undefined}
|
||||
links={panel.spec.links}
|
||||
canSetDashboardVariables={dashboardVariables.hasFieldVariables}
|
||||
onViewLogs={(): void => navigate('view_logs')}
|
||||
onViewTraces={(): void => navigate('view_traces')}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { toast } from '@signozhq/ui/sonner';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import type { TelemetrytypesSignalDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import { DashboardtypesDynamicVariableSignalDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import type { FilterData } from 'container/QueryTable/Drilldown/drilldownUtils';
|
||||
import {
|
||||
dtoToFormModel,
|
||||
formModelToDto,
|
||||
} from 'pages/DashboardPageV2/DashboardContainer/DashboardSettings/Variables/variableAdapters';
|
||||
import {
|
||||
DYNAMIC_SIGNAL_ALL,
|
||||
emptyVariableFormModel,
|
||||
type VariableFormModel,
|
||||
} from 'pages/DashboardPageV2/DashboardContainer/DashboardSettings/Variables/variableFormModel';
|
||||
@@ -23,8 +22,8 @@ import { DashboardDetailEvents } from 'pages/DashboardPageV2/constants/events';
|
||||
interface UseDrilldownDashboardVariablesArgs {
|
||||
/** Group-by field filters from the clicked point (empty when the click has no group-by). */
|
||||
filters: FilterData[];
|
||||
/** Clicked query's telemetry signal — seeds a created variable's `dynamicSignal`. */
|
||||
signal?: TelemetrytypesSignalDTO;
|
||||
/** Dynamic-variable signal derived from the clicked query — seeds a created variable's `dynamicSignal`. */
|
||||
signal?: DashboardtypesDynamicVariableSignalDTO;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
@@ -111,8 +110,7 @@ export function useDrilldownDashboardVariables({
|
||||
type: 'DYNAMIC',
|
||||
multiSelect: true,
|
||||
dynamicAttribute: fieldName,
|
||||
// `||` (not `??`): an empty "any" signal maps to All, same as unset.
|
||||
dynamicSignal: signal || DYNAMIC_SIGNAL_ALL,
|
||||
dynamicSignal: signal ?? DashboardtypesDynamicVariableSignalDTO.all,
|
||||
};
|
||||
try {
|
||||
await patchAsync(
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import type { DashboardtypesGettableDashboardV2DTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import {
|
||||
DashboardtypesDynamicVariableSignalDTO,
|
||||
type DashboardtypesGettableDashboardV2DTO,
|
||||
} from 'api/generated/services/sigNoz.schemas';
|
||||
import { setDashboardVariablesStore } from 'providers/Dashboard/store/dashboardVariables/dashboardVariablesStore';
|
||||
import type {
|
||||
IDashboardVariable,
|
||||
@@ -8,7 +11,6 @@ import type {
|
||||
|
||||
import { dtoToFormModel } from '../DashboardSettings/Variables/variableAdapters';
|
||||
import {
|
||||
DYNAMIC_SIGNAL_ALL,
|
||||
type VariableFormModel,
|
||||
type VariableType,
|
||||
} from '../DashboardSettings/Variables/variableFormModel';
|
||||
@@ -35,7 +37,7 @@ function toV1Variable(model: VariableFormModel): IDashboardVariable {
|
||||
showALLOption: model.showAllOption,
|
||||
dynamicVariablesAttribute: model.dynamicAttribute,
|
||||
dynamicVariablesSource:
|
||||
model.dynamicSignal === DYNAMIC_SIGNAL_ALL
|
||||
model.dynamicSignal === DashboardtypesDynamicVariableSignalDTO.all
|
||||
? 'all sources'
|
||||
: model.dynamicSignal,
|
||||
};
|
||||
|
||||
@@ -49,6 +49,7 @@ export function createDefaultPanel(
|
||||
spec: pluginSpec,
|
||||
} as DashboardtypesPanelPluginDTO,
|
||||
queries,
|
||||
links: [],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ function BlankDashboardPanel({ onClose }: Props): JSX.Element {
|
||||
layouts: [],
|
||||
panels: {},
|
||||
variables: [],
|
||||
links: [],
|
||||
},
|
||||
});
|
||||
void logEvent(DashboardListEvents.DashboardCreated, {
|
||||
|
||||
@@ -21,6 +21,7 @@ import { DataSource } from 'types/common/queryBuilder';
|
||||
import { TraceDetailEventKeys, TraceDetailEvents } from '../events';
|
||||
import { useTraceDetailLogEvent } from '../hooks/useTraceDetailLogEvent';
|
||||
import { useTraceStore } from '../stores/traceStore';
|
||||
import TraceDownloadPanel from './TraceDownloadPanel';
|
||||
import EntityMetadataRow from '../EntityMetadata/EntityMetadataRow';
|
||||
import AnalyticsPanel from '../SpanDetailsPanel/AnalyticsPanel/AnalyticsPanel';
|
||||
import Filters from '../TraceWaterfall/TraceWaterfallStates/Success/Filters/Filters';
|
||||
@@ -43,6 +44,7 @@ export interface TraceMetadataForHeader {
|
||||
rootServiceEntryPoint: string;
|
||||
rootSpanStatusCode: string;
|
||||
hasMissingSpans: boolean;
|
||||
totalSpansCount: number;
|
||||
}
|
||||
|
||||
interface TraceDetailsHeaderProps {
|
||||
@@ -168,6 +170,10 @@ function TraceDetailsHeader({
|
||||
showTraceDetails={showTraceDetails}
|
||||
onToggleTraceDetails={handleToggleTraceDetails}
|
||||
onOpenPreviewFields={(): void => setIsPreviewFieldsOpen(true)}
|
||||
traceId={traceID || ''}
|
||||
startTime={filterMetadata.startTime}
|
||||
endTime={filterMetadata.endTime}
|
||||
totalSpansCount={traceMetadata?.totalSpansCount || 0}
|
||||
/>
|
||||
</div>
|
||||
</TooltipProvider>
|
||||
@@ -228,6 +234,8 @@ function TraceDetailsHeader({
|
||||
onClose={(): void => setIsAnalyticsOpen(false)}
|
||||
onTabChange={handleAnalyticsTabChange}
|
||||
/>
|
||||
|
||||
<TraceDownloadPanel />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
.downloadPanel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-3);
|
||||
padding: var(--spacing-4);
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-3);
|
||||
}
|
||||
|
||||
.title {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-2);
|
||||
font-size: var(--paragraph-base-400-font-size);
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: var(--secondary-foreground);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.loader {
|
||||
color: var(--bg-robin-500);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.percent {
|
||||
font-size: var(--paragraph-base-400-font-size);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
color: var(--l2-foreground);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.cancelBtn {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
flex-shrink: 0;
|
||||
color: var(--l2-foreground);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import { useEffect } from 'react';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Progress } from '@signozhq/ui/progress';
|
||||
import { LoaderCircle, X } from '@signozhq/icons';
|
||||
import { FloatingPanel } from 'periscope/components/FloatingPanel';
|
||||
|
||||
import { useTraceDownloadStore } from './traceDownloadStore';
|
||||
|
||||
import styles from './TraceDownloadPanel.module.scss';
|
||||
|
||||
const PANEL_WIDTH = 356;
|
||||
const PANEL_HEIGHT = 76;
|
||||
|
||||
function TraceDownloadPanel(): JSX.Element {
|
||||
const isDownloading = useTraceDownloadStore((s) => s.isDownloading);
|
||||
const progress = useTraceDownloadStore((s) => s.progress);
|
||||
const cancelDownload = useTraceDownloadStore((s) => s.cancelDownload);
|
||||
|
||||
useEffect(() => cancelDownload, [cancelDownload]);
|
||||
|
||||
const displayProgress = Math.max(1, progress);
|
||||
|
||||
return (
|
||||
<FloatingPanel
|
||||
isOpen={isDownloading}
|
||||
width={PANEL_WIDTH}
|
||||
height={PANEL_HEIGHT}
|
||||
minWidth={PANEL_WIDTH}
|
||||
minHeight={PANEL_HEIGHT}
|
||||
enableResizing={false}
|
||||
>
|
||||
<div className={styles.downloadPanel} data-testid="trace-download-panel">
|
||||
<div className={`${styles.header} floating-panel__drag-handle`}>
|
||||
<span className={styles.title}>
|
||||
Downloading trace
|
||||
<LoaderCircle size={14} className={`animate-spin ${styles.loader}`} />
|
||||
</span>
|
||||
<span className={styles.percent} data-testid="trace-download-percent">
|
||||
{displayProgress}%
|
||||
</span>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
color="secondary"
|
||||
className={styles.cancelBtn}
|
||||
onClick={cancelDownload}
|
||||
aria-label="Cancel download"
|
||||
data-testid="trace-download-cancel"
|
||||
prefix={<X size={16} />}
|
||||
/>
|
||||
</div>
|
||||
<Progress percent={displayProgress} status="active" showInfo={false} />
|
||||
</div>
|
||||
</FloatingPanel>
|
||||
);
|
||||
}
|
||||
|
||||
export default TraceDownloadPanel;
|
||||
@@ -12,8 +12,10 @@ import {
|
||||
DropdownMenuTrigger,
|
||||
} from '@signozhq/ui/dropdown-menu';
|
||||
import { Settings2 } from '@signozhq/icons';
|
||||
import { ExportFormat } from 'lib/exportData/types';
|
||||
|
||||
import { useTraceStore } from '../stores/traceStore';
|
||||
import { useDownloadTrace } from './useDownloadTrace';
|
||||
|
||||
import styles from './TraceOptionsMenu.module.scss';
|
||||
|
||||
@@ -21,6 +23,10 @@ interface TraceOptionsMenuProps {
|
||||
showTraceDetails: boolean;
|
||||
onToggleTraceDetails: () => void;
|
||||
onOpenPreviewFields: () => void;
|
||||
traceId: string;
|
||||
startTime: number;
|
||||
endTime: number;
|
||||
totalSpansCount: number;
|
||||
}
|
||||
|
||||
// Composed from dropdown-menu primitives (instead of DropdownMenuSimple)
|
||||
@@ -30,6 +36,10 @@ function TraceOptionsMenu({
|
||||
showTraceDetails,
|
||||
onToggleTraceDetails,
|
||||
onOpenPreviewFields,
|
||||
traceId,
|
||||
startTime,
|
||||
endTime,
|
||||
totalSpansCount,
|
||||
}: TraceOptionsMenuProps): JSX.Element {
|
||||
const colorByField = useTraceStore((s) => s.colorByField);
|
||||
const setColorByField = useTraceStore((s) => s.setColorByField);
|
||||
@@ -37,6 +47,13 @@ function TraceOptionsMenu({
|
||||
(s) => s.availableColorByOptions,
|
||||
);
|
||||
|
||||
const { isDownloading, isExportDisabled, downloadTrace } = useDownloadTrace({
|
||||
traceId,
|
||||
startTime,
|
||||
endTime,
|
||||
totalSpansCount,
|
||||
});
|
||||
|
||||
const handleColorByChange = (name: string): void => {
|
||||
const next = availableColorByOptions.find((o) => o.field.name === name);
|
||||
if (next) {
|
||||
@@ -81,6 +98,32 @@ function TraceOptionsMenu({
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuSub>
|
||||
)}
|
||||
{!isExportDisabled && (
|
||||
<DropdownMenuSub>
|
||||
<DropdownMenuSubTrigger
|
||||
disabled={isDownloading}
|
||||
data-testid="download-trace-submenu"
|
||||
>
|
||||
Download trace
|
||||
</DropdownMenuSubTrigger>
|
||||
<DropdownMenuSubContent className={styles.traceOptionsDropdown}>
|
||||
<DropdownMenuItem
|
||||
clickable
|
||||
onSelect={(): void => downloadTrace(ExportFormat.Csv)}
|
||||
testId="download-trace-csv"
|
||||
>
|
||||
CSV
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
clickable
|
||||
onSelect={(): void => downloadTrace(ExportFormat.Jsonl)}
|
||||
testId="download-trace-jsonl"
|
||||
>
|
||||
JSONL
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuSub>
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
|
||||
@@ -141,6 +141,7 @@ describe('TraceDetailsHeader – trace metadata row', () => {
|
||||
rootServiceEntryPoint: 'large-trace-root',
|
||||
rootSpanStatusCode: '404',
|
||||
hasMissingSpans: false,
|
||||
totalSpansCount: 42,
|
||||
};
|
||||
|
||||
it('renders the metadata (service, entry point, duration, status) when provided', () => {
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
import 'tests/blob-polyfill';
|
||||
|
||||
import { screen, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { fetchExportData } from 'api/v1/download/downloadExportData';
|
||||
import { downloadFile } from 'lib/exportData/downloadFile';
|
||||
import { render } from 'tests/test-utils';
|
||||
|
||||
import TraceDownloadPanel from '../TraceDownloadPanel';
|
||||
import TraceOptionsMenu from '../TraceOptionsMenu';
|
||||
import { MAX_EXPORT_SPANS } from '../useDownloadTrace';
|
||||
|
||||
// Integration suite: menu → hook → store → runner → stitchers → panel all run
|
||||
// for real; only the true boundaries are mocked (HTTP + file save).
|
||||
jest.mock('api/v1/download/downloadExportData', () => ({
|
||||
fetchExportData: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('lib/exportData/downloadFile', () => ({
|
||||
downloadFile: jest.fn(),
|
||||
getTimestampedFileName: jest.fn(
|
||||
(base: string, ext: string) => `${base}.${ext}`,
|
||||
),
|
||||
}));
|
||||
|
||||
const mockFetch = fetchExportData as jest.Mock;
|
||||
const mockDownloadFile = downloadFile as jest.Mock;
|
||||
|
||||
const baseProps = {
|
||||
showTraceDetails: true,
|
||||
onToggleTraceDetails: jest.fn(),
|
||||
onOpenPreviewFields: jest.fn(),
|
||||
traceId: 'trace-123',
|
||||
startTime: 1_000,
|
||||
endTime: 2_000,
|
||||
// 120k spans → 3 export pages of 50k.
|
||||
totalSpansCount: 120_000,
|
||||
};
|
||||
|
||||
function renderFeature(
|
||||
props: Partial<typeof baseProps> = {},
|
||||
): ReturnType<typeof render> {
|
||||
return render(
|
||||
<>
|
||||
<TraceOptionsMenu {...baseProps} {...props} />
|
||||
<TraceDownloadPanel />
|
||||
</>,
|
||||
);
|
||||
}
|
||||
|
||||
// skipHover: simulated pointer travel fires pointerleave on the subtrigger and
|
||||
// radix's grace-area math (zero rects in jsdom) closes the submenu.
|
||||
// pointerEventsCheck 0: radix puts pointer-events:none on <body> while open.
|
||||
function setupUser(): ReturnType<typeof userEvent.setup> {
|
||||
return userEvent.setup({
|
||||
delay: null,
|
||||
skipHover: true,
|
||||
pointerEventsCheck: 0,
|
||||
});
|
||||
}
|
||||
|
||||
async function startDownload(
|
||||
format: 'csv' | 'jsonl' = 'csv',
|
||||
): Promise<ReturnType<typeof userEvent.setup>> {
|
||||
const user = setupUser();
|
||||
await user.click(screen.getByRole('button', { name: /trace options/i }));
|
||||
await user.click(await screen.findByTestId('download-trace-submenu'));
|
||||
await user.click(await screen.findByTestId(`download-trace-${format}`));
|
||||
return user;
|
||||
}
|
||||
|
||||
async function savedFileText(): Promise<string> {
|
||||
expect(mockDownloadFile).toHaveBeenCalledTimes(1);
|
||||
const [blob] = mockDownloadFile.mock.calls[0];
|
||||
return (blob as Blob).text();
|
||||
}
|
||||
|
||||
describe('trace download flow', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('downloads a multi-page trace as one stitched CSV', async () => {
|
||||
mockFetch.mockImplementation(({ body }) =>
|
||||
Promise.resolve(
|
||||
new Blob([`h1,h2\nrow-${body.compositeQuery.queries[0].spec.offset}\n`]),
|
||||
),
|
||||
);
|
||||
|
||||
renderFeature();
|
||||
await startDownload('csv');
|
||||
|
||||
await waitFor(() => expect(mockDownloadFile).toHaveBeenCalled());
|
||||
|
||||
// Real query building: trace scoping, page offsets, ±5min window (seconds→ms).
|
||||
const bodies = mockFetch.mock.calls.map(([props]) => props.body);
|
||||
const specs = bodies.map((b) => b.compositeQuery.queries[0].spec);
|
||||
expect(specs[0].filter.expression).toBe("trace_id = 'trace-123'");
|
||||
expect(specs.map((s) => s.offset).sort((a, b) => a - b)).toStrictEqual([
|
||||
0, 50_000, 100_000,
|
||||
]);
|
||||
expect(bodies[0].start).toBe((baseProps.startTime - 300) * 1e3);
|
||||
expect(bodies[0].end).toBe((baseProps.endTime + 300) * 1e3);
|
||||
|
||||
// Stitched in page order, headers deduped, saved under the trace's name.
|
||||
await expect(savedFileText()).resolves.toBe(
|
||||
'h1,h2\nrow-0\nrow-50000\nrow-100000\n',
|
||||
);
|
||||
expect(mockDownloadFile.mock.calls[0][1]).toBe('trace-trace-123.csv');
|
||||
|
||||
// Panel dismissed once the download completed.
|
||||
await waitFor(() =>
|
||||
expect(screen.queryByTestId('trace-download-panel')).not.toBeInTheDocument(),
|
||||
);
|
||||
});
|
||||
|
||||
it('downloads JSONL when that format is chosen', async () => {
|
||||
mockFetch.mockResolvedValue(new Blob(['{"a":1}\n']));
|
||||
|
||||
renderFeature({ totalSpansCount: 10 });
|
||||
await startDownload('jsonl');
|
||||
|
||||
await waitFor(() => expect(mockDownloadFile).toHaveBeenCalled());
|
||||
expect(mockFetch.mock.calls[0][0].format).toBe('jsonl');
|
||||
expect(mockDownloadFile.mock.calls[0][1]).toBe('trace-trace-123.jsonl');
|
||||
});
|
||||
|
||||
it('shows the progress panel while downloading and cancels from its ✕', async () => {
|
||||
// Fetches hang until aborted — the download stays in flight.
|
||||
mockFetch.mockImplementation(
|
||||
({ signal }) =>
|
||||
new Promise((_resolve, reject) => {
|
||||
signal.addEventListener('abort', () =>
|
||||
reject(new DOMException('Aborted', 'AbortError')),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
renderFeature();
|
||||
const user = await startDownload();
|
||||
|
||||
// Panel appears with the 1% floor (no part finished yet).
|
||||
const panel = await screen.findByTestId('trace-download-panel');
|
||||
expect(panel).toBeInTheDocument();
|
||||
expect(screen.getByTestId('trace-download-percent')).toHaveTextContent('1%');
|
||||
|
||||
await user.click(screen.getByTestId('trace-download-cancel'));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(screen.queryByTestId('trace-download-panel')).not.toBeInTheDocument(),
|
||||
);
|
||||
expect(mockDownloadFile).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('disables the submenu trigger while a download is running', async () => {
|
||||
mockFetch.mockImplementation(
|
||||
({ signal }) =>
|
||||
new Promise((_resolve, reject) => {
|
||||
signal.addEventListener('abort', () =>
|
||||
reject(new DOMException('Aborted', 'AbortError')),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
renderFeature();
|
||||
const user = await startDownload();
|
||||
|
||||
// Reopen the menu mid-download: trigger is disabled by REAL store state.
|
||||
await user.click(screen.getByRole('button', { name: /trace options/i }));
|
||||
const trigger = await screen.findByTestId('download-trace-submenu');
|
||||
expect(trigger).toHaveAttribute('data-disabled');
|
||||
|
||||
// Cleanup: stop the in-flight download so the module-scoped guard resets.
|
||||
await user.click(screen.getByTestId('trace-download-cancel'));
|
||||
await waitFor(() =>
|
||||
expect(screen.queryByTestId('trace-download-panel')).not.toBeInTheDocument(),
|
||||
);
|
||||
});
|
||||
|
||||
it('hides the download option entirely above the export cap', async () => {
|
||||
renderFeature({ totalSpansCount: MAX_EXPORT_SPANS + 1 });
|
||||
const user = setupUser();
|
||||
await user.click(screen.getByRole('button', { name: /trace options/i }));
|
||||
|
||||
await expect(
|
||||
screen.findByRole('menuitem', { name: /preview fields/i }),
|
||||
).resolves.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByTestId('download-trace-submenu'),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('saves nothing and dismisses the panel when a page fails', async () => {
|
||||
mockFetch.mockRejectedValue(new Error('boom'));
|
||||
|
||||
renderFeature();
|
||||
await startDownload();
|
||||
|
||||
await waitFor(() =>
|
||||
expect(screen.queryByTestId('trace-download-panel')).not.toBeInTheDocument(),
|
||||
);
|
||||
expect(mockDownloadFile).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('cancels the in-flight download when the panel unmounts (leaving the page)', async () => {
|
||||
const seenSignals: AbortSignal[] = [];
|
||||
mockFetch.mockImplementation(
|
||||
({ signal }) =>
|
||||
new Promise((_resolve, reject) => {
|
||||
seenSignals.push(signal);
|
||||
signal.addEventListener('abort', () =>
|
||||
reject(new DOMException('Aborted', 'AbortError')),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
const { unmount } = renderFeature();
|
||||
await startDownload();
|
||||
await screen.findByTestId('trace-download-panel');
|
||||
|
||||
unmount();
|
||||
|
||||
await waitFor(() =>
|
||||
expect(seenSignals.every((signal) => signal.aborted)).toBe(true),
|
||||
);
|
||||
expect(mockDownloadFile).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,63 @@
|
||||
import {
|
||||
ChunkedExportArgs,
|
||||
runChunkedExport,
|
||||
} from 'hooks/useExportData/runChunkedExport';
|
||||
import { ExportFormat } from 'lib/exportData/types';
|
||||
import { create } from 'zustand';
|
||||
|
||||
/** 'skipped' = a download was already in flight; the call was ignored. */
|
||||
export type TraceDownloadOutcome = 'completed' | 'cancelled' | 'skipped';
|
||||
|
||||
interface TraceDownloadState {
|
||||
isDownloading: boolean;
|
||||
// 0–100
|
||||
progress: number;
|
||||
startDownload: (
|
||||
args: ChunkedExportArgs & { format: ExportFormat },
|
||||
) => Promise<TraceDownloadOutcome>;
|
||||
cancelDownload: () => void;
|
||||
}
|
||||
|
||||
let abortController: AbortController | null = null;
|
||||
|
||||
export const useTraceDownloadStore = create<TraceDownloadState>((set) => ({
|
||||
isDownloading: false,
|
||||
progress: 0,
|
||||
|
||||
startDownload: async ({
|
||||
format,
|
||||
...args
|
||||
}: ChunkedExportArgs & {
|
||||
format: ExportFormat;
|
||||
}): Promise<TraceDownloadOutcome> => {
|
||||
if (abortController) {
|
||||
return 'skipped';
|
||||
}
|
||||
|
||||
const controller = new AbortController();
|
||||
abortController = controller;
|
||||
set({ isDownloading: true, progress: 0 });
|
||||
|
||||
try {
|
||||
await runChunkedExport({
|
||||
...args,
|
||||
format,
|
||||
signal: controller.signal,
|
||||
onProgress: (progress: number): void => set({ progress }),
|
||||
});
|
||||
return 'completed';
|
||||
} catch (error) {
|
||||
if (controller.signal.aborted) {
|
||||
return 'cancelled';
|
||||
}
|
||||
throw error;
|
||||
} finally {
|
||||
abortController = null;
|
||||
set({ isDownloading: false });
|
||||
}
|
||||
},
|
||||
|
||||
cancelDownload: (): void => {
|
||||
abortController?.abort();
|
||||
},
|
||||
}));
|
||||
@@ -0,0 +1,23 @@
|
||||
import { listViewInitialTraceQuery } from 'constants/queryBuilder';
|
||||
import { LogsAggregatorOperator } from 'types/common/queryBuilder';
|
||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||
|
||||
export function getTraceExportQuery(traceId: string): Query {
|
||||
const [baseQueryData] = listViewInitialTraceQuery.builder.queryData;
|
||||
|
||||
return {
|
||||
...listViewInitialTraceQuery,
|
||||
builder: {
|
||||
...listViewInitialTraceQuery.builder,
|
||||
queryData: [
|
||||
{
|
||||
...baseQueryData,
|
||||
aggregateOperator: LogsAggregatorOperator.NOOP,
|
||||
filter: { expression: `trace_id = '${traceId}'` },
|
||||
orderBy: [{ columnName: 'timestamp', order: 'asc' }],
|
||||
selectColumns: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { toast } from '@signozhq/ui/sonner';
|
||||
import { ExportFormat } from 'lib/exportData/types';
|
||||
|
||||
import { TraceDetailEventKeys, TraceDetailEvents } from '../events';
|
||||
import { useTraceDetailLogEvent } from '../hooks/useTraceDetailLogEvent';
|
||||
import { useTraceDownloadStore } from './traceDownloadStore';
|
||||
import { getTraceExportQuery } from './traceExportQuery';
|
||||
|
||||
// Export window pad past the trace bounds so edge spans are never clipped
|
||||
// (mirrors SpanDetailsPanel).
|
||||
const FIVE_MINUTES_IN_SECONDS = 5 * 60;
|
||||
|
||||
// Span-count cap: traces above it hide their download option entirely.
|
||||
export const MAX_EXPORT_SPANS = 500_000;
|
||||
|
||||
interface UseDownloadTraceProps {
|
||||
traceId: string;
|
||||
// Trace start/end in seconds.
|
||||
startTime: number;
|
||||
endTime: number;
|
||||
totalSpansCount: number;
|
||||
}
|
||||
|
||||
interface UseDownloadTraceReturn {
|
||||
isDownloading: boolean;
|
||||
isExportDisabled: boolean;
|
||||
downloadTrace: (format: ExportFormat) => void;
|
||||
}
|
||||
|
||||
export function useDownloadTrace({
|
||||
traceId,
|
||||
startTime,
|
||||
endTime,
|
||||
totalSpansCount,
|
||||
}: UseDownloadTraceProps): UseDownloadTraceReturn {
|
||||
const isDownloading = useTraceDownloadStore((s) => s.isDownloading);
|
||||
const startDownload = useTraceDownloadStore((s) => s.startDownload);
|
||||
|
||||
const logTraceEvent = useTraceDetailLogEvent('v3', traceId);
|
||||
|
||||
const query = useMemo(() => getTraceExportQuery(traceId), [traceId]);
|
||||
|
||||
const timeRange = useMemo(
|
||||
() => ({
|
||||
start: startTime - FIVE_MINUTES_IN_SECONDS,
|
||||
end: endTime + FIVE_MINUTES_IN_SECONDS,
|
||||
}),
|
||||
[startTime, endTime],
|
||||
);
|
||||
|
||||
const downloadTrace = useCallback(
|
||||
(format: ExportFormat): void => {
|
||||
logTraceEvent(TraceDetailEvents.DownloadTriggered, {
|
||||
[TraceDetailEventKeys.Format]: format,
|
||||
[TraceDetailEventKeys.TotalSpansCount]: totalSpansCount,
|
||||
});
|
||||
|
||||
const run = async (): Promise<void> => {
|
||||
try {
|
||||
const outcome = await startDownload({
|
||||
query,
|
||||
timeRange,
|
||||
totalRows: totalSpansCount,
|
||||
fileNameBase: `trace-${traceId}`,
|
||||
format,
|
||||
});
|
||||
if (outcome === 'completed') {
|
||||
toast.success('Export completed successfully');
|
||||
} else if (outcome === 'cancelled') {
|
||||
logTraceEvent(TraceDetailEvents.DownloadCancelled, {
|
||||
[TraceDetailEventKeys.Format]: format,
|
||||
[TraceDetailEventKeys.TotalSpansCount]: totalSpansCount,
|
||||
});
|
||||
toast.info('Export cancelled');
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error('Failed to download trace');
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
void run();
|
||||
},
|
||||
[query, timeRange, totalSpansCount, traceId, startDownload, logTraceEvent],
|
||||
);
|
||||
|
||||
return {
|
||||
isDownloading,
|
||||
isExportDisabled: totalSpansCount > MAX_EXPORT_SPANS,
|
||||
downloadTrace,
|
||||
};
|
||||
}
|
||||
@@ -6,6 +6,8 @@ export enum TraceDetailEvents {
|
||||
AnalyticsPanelToggled = 'Trace Detail: Analytics panel toggled',
|
||||
AnalyticsTabChanged = 'Trace Detail: Analytics tab changed',
|
||||
SpanPanelTabChanged = 'Trace Detail: Span panel tab changed',
|
||||
DownloadTriggered = 'Trace Detail: Download triggered',
|
||||
DownloadCancelled = 'Trace Detail: Download cancelled',
|
||||
}
|
||||
|
||||
export enum TraceDetailEventKeys {
|
||||
@@ -32,6 +34,8 @@ export enum TraceDetailEventKeys {
|
||||
Tab = 'tab',
|
||||
// Span panel tab changed
|
||||
SpanId = 'spanId',
|
||||
// Download triggered (reuses TotalSpansCount for trace size)
|
||||
Format = 'format',
|
||||
}
|
||||
|
||||
export type TraceDetailView = 'v2' | 'v3';
|
||||
|
||||
@@ -346,6 +346,7 @@ function TraceDetailsV3(): JSX.Element {
|
||||
rootServiceEntryPoint: payload.rootServiceEntryPoint,
|
||||
rootSpanStatusCode: rootSpan?.response_status_code || '',
|
||||
hasMissingSpans: payload.hasMissingSpans || false,
|
||||
totalSpansCount: payload.totalSpansCount || 0,
|
||||
};
|
||||
}, [traceData?.payload]);
|
||||
|
||||
|
||||
34
frontend/src/tests/blob-polyfill.ts
Normal file
34
frontend/src/tests/blob-polyfill.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* jsdom's Blob lacks the modern read methods (arrayBuffer/text). Polyfill via
|
||||
* FileReader (which jsdom does implement); guarded, so it no-ops once jsdom
|
||||
* catches up. Side-effect module — import it at the top of any test touching
|
||||
* Blob contents:
|
||||
*
|
||||
* import 'tests/blob-polyfill';
|
||||
*/
|
||||
|
||||
if (typeof Blob.prototype.arrayBuffer === 'undefined') {
|
||||
Blob.prototype.arrayBuffer = function arrayBuffer(
|
||||
this: Blob,
|
||||
): Promise<ArrayBuffer> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (): void => resolve(reader.result as ArrayBuffer);
|
||||
reader.onerror = (): void => reject(reader.error);
|
||||
reader.readAsArrayBuffer(this);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof Blob.prototype.text === 'undefined') {
|
||||
Blob.prototype.text = function text(this: Blob): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (): void => resolve(reader.result as string);
|
||||
reader.onerror = (): void => reject(reader.error);
|
||||
reader.readAsText(this);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export {};
|
||||
@@ -32,11 +32,12 @@ unaryExpression
|
||||
;
|
||||
|
||||
// Primary constructs: grouped expressions, a comparison (key op value),
|
||||
// a function call, or a full-text string
|
||||
// a function call, a search() full-text call, or a free-text string
|
||||
primary
|
||||
: LPAREN orExpression RPAREN
|
||||
| comparison
|
||||
| functionCall
|
||||
| searchCall
|
||||
| fullText
|
||||
| key
|
||||
| value
|
||||
@@ -110,6 +111,18 @@ functionCall
|
||||
: (HASTOKEN | HAS | HASANY | HASALL) LPAREN functionParamList RPAREN
|
||||
;
|
||||
|
||||
/*
|
||||
* Full-text search call: search('needle')
|
||||
*
|
||||
* Uses the shared functionParamList so future scoped forms like
|
||||
* search(body, 'abc') / search(attribute, 'abc') need no grammar change. Today
|
||||
* only a single needle is supported. Unlike bare/quoted free text (`fullText`),
|
||||
* which only targets the body column, search() fans out across every field.
|
||||
*/
|
||||
searchCall
|
||||
: SEARCH LPAREN functionParamList RPAREN
|
||||
;
|
||||
|
||||
// Function parameters can be keys, single scalar values, or arrays
|
||||
functionParamList
|
||||
: functionParam ( COMMA functionParam )*
|
||||
@@ -184,6 +197,7 @@ HASTOKEN : [Hh][Aa][Ss][Tt][Oo][Kk][Ee][Nn];
|
||||
HAS : [Hh][Aa][Ss] ;
|
||||
HASANY : [Hh][Aa][Ss][Aa][Nn][Yy] ;
|
||||
HASALL : [Hh][Aa][Ss][Aa][Ll][Ll] ;
|
||||
SEARCH : [Ss][Ee][Aa][Rr][Cc][Hh] ;
|
||||
|
||||
// Potential boolean constants
|
||||
BOOL
|
||||
|
||||
@@ -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 status (kubectl-style display status such as Running/Pending/CrashLoopBackOff, or 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 status) or 'grouped_list' for custom groupBy keys (each row aggregates pods in the group with per-status counts under podCountsByStatus: { pending, running, failed, unknown, crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError, containerCreating, oomKilled, completed, error, containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } derived from each pod's latest kubectl-style display status 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.",
|
||||
Request: new(inframonitoringtypes.PostablePods),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(inframonitoringtypes.Pods),
|
||||
@@ -73,7 +73,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 podCountsByStatus ({ pending, running, failed, unknown, crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError, containerCreating, oomKilled, completed, error, containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } for pods scheduled on the listed nodes, reflecting each pod's latest kubectl-style display status). 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.",
|
||||
Request: new(inframonitoringtypes.PostableNodes),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(inframonitoringtypes.Nodes),
|
||||
@@ -92,7 +92,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 podCountsByStatus ({ pending, running, failed, unknown, crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError, containerCreating, oomKilled, completed, error, containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } reflecting each pod's latest kubectl-style display status 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.",
|
||||
Request: new(inframonitoringtypes.PostableNamespaces),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(inframonitoringtypes.Namespaces),
|
||||
@@ -111,7 +111,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 podCountsByStatus ({ pending, running, failed, unknown, crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError, containerCreating, oomKilled, completed, error, containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } reflecting each pod's latest kubectl-style display status). 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.",
|
||||
Request: new(inframonitoringtypes.PostableClusters),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(inframonitoringtypes.Clusters),
|
||||
@@ -149,7 +149,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 podCountsByStatus ({ pending, running, failed, unknown, crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError, containerCreating, oomKilled, completed, error, containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } reflecting each pod's latest kubectl-style display status). 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.",
|
||||
Request: new(inframonitoringtypes.PostableDeployments),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(inframonitoringtypes.Deployments),
|
||||
@@ -168,7 +168,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 podCountsByStatus ({ pending, running, failed, unknown, crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError, containerCreating, oomKilled, completed, error, containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } reflecting each pod's latest kubectl-style display status). 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.",
|
||||
Request: new(inframonitoringtypes.PostableStatefulSets),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(inframonitoringtypes.StatefulSets),
|
||||
@@ -187,7 +187,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 podCountsByStatus ({ pending, running, failed, unknown, crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError, containerCreating, oomKilled, completed, error, containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } reflecting each pod's latest kubectl-style display status); note podCountsByStatus.failed (current pod status) 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.",
|
||||
Request: new(inframonitoringtypes.PostableJobs),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(inframonitoringtypes.Jobs),
|
||||
@@ -206,7 +206,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), currentNodes (k8s.daemonset.current_scheduled_nodes, the number of nodes the daemonset currently runs on), readyNodes (k8s.daemonset.ready_nodes, the number of nodes running at least one ready daemon pod) and misscheduledNodes (k8s.daemonset.misscheduled_nodes, the number of nodes running the daemon pod but not supposed to) — 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 / ready_nodes / misscheduled_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, readyNodes, misscheduledNodes) 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), currentNodes (k8s.daemonset.current_scheduled_nodes, the number of nodes the daemonset currently runs on), readyNodes (k8s.daemonset.ready_nodes, the number of nodes running at least one ready daemon pod) and misscheduledNodes (k8s.daemonset.misscheduled_nodes, the number of nodes running the daemon pod but not supposed to) — note these are node counts, not pod counts. It also reports per-group podCountsByStatus ({ pending, running, failed, unknown, crashLoopBackOff, imagePullBackOff, errImagePull, createContainerConfigError, containerCreating, oomKilled, completed, error, containerCannotRun, evicted, nodeAffinity, nodeLost, shutdown, unexpectedAdmissionError } reflecting each pod's latest kubectl-style display status). 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 / ready_nodes / misscheduled_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, readyNodes, misscheduledNodes) return -1 as a sentinel when no data is available for that field.",
|
||||
Request: new(inframonitoringtypes.PostableDaemonSets),
|
||||
RequestContentType: "application/json",
|
||||
Response: new(inframonitoringtypes.DaemonSets),
|
||||
|
||||
@@ -101,12 +101,12 @@ func PrepareFilterExpression(labels map[string]string, whereClause string, group
|
||||
}
|
||||
|
||||
// Visit implements the visitor for the query rule.
|
||||
func (r *WhereClauseRewriter) Visit(tree antlr.ParseTree) interface{} {
|
||||
func (r *WhereClauseRewriter) Visit(tree antlr.ParseTree) any {
|
||||
return tree.Accept(r)
|
||||
}
|
||||
|
||||
// VisitQuery visits the query node.
|
||||
func (r *WhereClauseRewriter) VisitQuery(ctx *parser.QueryContext) interface{} {
|
||||
func (r *WhereClauseRewriter) VisitQuery(ctx *parser.QueryContext) any {
|
||||
if ctx.Expression() != nil {
|
||||
ctx.Expression().Accept(r)
|
||||
}
|
||||
@@ -114,7 +114,7 @@ func (r *WhereClauseRewriter) VisitQuery(ctx *parser.QueryContext) interface{} {
|
||||
}
|
||||
|
||||
// VisitExpression visits the expression node.
|
||||
func (r *WhereClauseRewriter) VisitExpression(ctx *parser.ExpressionContext) interface{} {
|
||||
func (r *WhereClauseRewriter) VisitExpression(ctx *parser.ExpressionContext) any {
|
||||
if ctx.OrExpression() != nil {
|
||||
ctx.OrExpression().Accept(r)
|
||||
}
|
||||
@@ -122,7 +122,7 @@ func (r *WhereClauseRewriter) VisitExpression(ctx *parser.ExpressionContext) int
|
||||
}
|
||||
|
||||
// VisitOrExpression visits OR expressions.
|
||||
func (r *WhereClauseRewriter) VisitOrExpression(ctx *parser.OrExpressionContext) interface{} {
|
||||
func (r *WhereClauseRewriter) VisitOrExpression(ctx *parser.OrExpressionContext) any {
|
||||
for i, andExpr := range ctx.AllAndExpression() {
|
||||
if i > 0 {
|
||||
r.rewritten.WriteString(" OR ")
|
||||
@@ -133,7 +133,7 @@ func (r *WhereClauseRewriter) VisitOrExpression(ctx *parser.OrExpressionContext)
|
||||
}
|
||||
|
||||
// VisitAndExpression visits AND expressions.
|
||||
func (r *WhereClauseRewriter) VisitAndExpression(ctx *parser.AndExpressionContext) interface{} {
|
||||
func (r *WhereClauseRewriter) VisitAndExpression(ctx *parser.AndExpressionContext) any {
|
||||
unaryExprs := ctx.AllUnaryExpression()
|
||||
for i, unaryExpr := range unaryExprs {
|
||||
if i > 0 {
|
||||
@@ -151,7 +151,7 @@ func (r *WhereClauseRewriter) VisitAndExpression(ctx *parser.AndExpressionContex
|
||||
}
|
||||
|
||||
// VisitUnaryExpression visits unary expressions (with optional NOT).
|
||||
func (r *WhereClauseRewriter) VisitUnaryExpression(ctx *parser.UnaryExpressionContext) interface{} {
|
||||
func (r *WhereClauseRewriter) VisitUnaryExpression(ctx *parser.UnaryExpressionContext) any {
|
||||
if ctx.NOT() != nil {
|
||||
r.rewritten.WriteString("NOT ")
|
||||
}
|
||||
@@ -162,7 +162,7 @@ func (r *WhereClauseRewriter) VisitUnaryExpression(ctx *parser.UnaryExpressionCo
|
||||
}
|
||||
|
||||
// VisitPrimary visits primary expressions.
|
||||
func (r *WhereClauseRewriter) VisitPrimary(ctx *parser.PrimaryContext) interface{} {
|
||||
func (r *WhereClauseRewriter) VisitPrimary(ctx *parser.PrimaryContext) any {
|
||||
if ctx.LPAREN() != nil && ctx.RPAREN() != nil {
|
||||
r.rewritten.WriteString("(")
|
||||
if ctx.OrExpression() != nil {
|
||||
@@ -173,6 +173,8 @@ func (r *WhereClauseRewriter) VisitPrimary(ctx *parser.PrimaryContext) interface
|
||||
ctx.Comparison().Accept(r)
|
||||
} else if ctx.FunctionCall() != nil {
|
||||
ctx.FunctionCall().Accept(r)
|
||||
} else if ctx.SearchCall() != nil {
|
||||
ctx.SearchCall().Accept(r)
|
||||
} else if ctx.FullText() != nil {
|
||||
ctx.FullText().Accept(r)
|
||||
} else if ctx.Key() != nil {
|
||||
@@ -184,7 +186,7 @@ func (r *WhereClauseRewriter) VisitPrimary(ctx *parser.PrimaryContext) interface
|
||||
}
|
||||
|
||||
// VisitComparison visits comparison expressions.
|
||||
func (r *WhereClauseRewriter) VisitComparison(ctx *parser.ComparisonContext) interface{} {
|
||||
func (r *WhereClauseRewriter) VisitComparison(ctx *parser.ComparisonContext) any {
|
||||
if ctx.Key() == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -197,7 +199,7 @@ func (r *WhereClauseRewriter) VisitComparison(ctx *parser.ComparisonContext) int
|
||||
if _, partOfGroup := r.groupBySet[key]; partOfGroup {
|
||||
// Case 1: Replace with actual value
|
||||
escapedValue := escapeValueIfNeeded(value)
|
||||
r.rewritten.WriteString(fmt.Sprintf("%s=%s", key, escapedValue))
|
||||
fmt.Fprintf(&r.rewritten, "%s=%s", key, escapedValue)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -305,7 +307,7 @@ func (r *WhereClauseRewriter) VisitComparison(ctx *parser.ComparisonContext) int
|
||||
}
|
||||
|
||||
// VisitInClause visits IN clauses.
|
||||
func (r *WhereClauseRewriter) VisitInClause(ctx *parser.InClauseContext) interface{} {
|
||||
func (r *WhereClauseRewriter) VisitInClause(ctx *parser.InClauseContext) any {
|
||||
r.rewritten.WriteString("IN ")
|
||||
if ctx.LPAREN() != nil {
|
||||
r.rewritten.WriteString("(")
|
||||
@@ -326,7 +328,7 @@ func (r *WhereClauseRewriter) VisitInClause(ctx *parser.InClauseContext) interfa
|
||||
}
|
||||
|
||||
// VisitNotInClause visits NOT IN clauses.
|
||||
func (r *WhereClauseRewriter) VisitNotInClause(ctx *parser.NotInClauseContext) interface{} {
|
||||
func (r *WhereClauseRewriter) VisitNotInClause(ctx *parser.NotInClauseContext) any {
|
||||
r.rewritten.WriteString("NOT IN ")
|
||||
if ctx.LPAREN() != nil {
|
||||
r.rewritten.WriteString("(")
|
||||
@@ -347,7 +349,7 @@ func (r *WhereClauseRewriter) VisitNotInClause(ctx *parser.NotInClauseContext) i
|
||||
}
|
||||
|
||||
// VisitValueList visits value lists.
|
||||
func (r *WhereClauseRewriter) VisitValueList(ctx *parser.ValueListContext) interface{} {
|
||||
func (r *WhereClauseRewriter) VisitValueList(ctx *parser.ValueListContext) any {
|
||||
values := ctx.AllValue()
|
||||
for i, val := range values {
|
||||
if i > 0 {
|
||||
@@ -359,13 +361,20 @@ func (r *WhereClauseRewriter) VisitValueList(ctx *parser.ValueListContext) inter
|
||||
}
|
||||
|
||||
// VisitFullText visits full text expressions.
|
||||
func (r *WhereClauseRewriter) VisitFullText(ctx *parser.FullTextContext) interface{} {
|
||||
func (r *WhereClauseRewriter) VisitFullText(ctx *parser.FullTextContext) any {
|
||||
r.rewritten.WriteString(ctx.GetText())
|
||||
return nil
|
||||
}
|
||||
|
||||
// VisitSearchCall visits search() calls. It has no keys to rewrite, so it is
|
||||
// preserved verbatim.
|
||||
func (r *WhereClauseRewriter) VisitSearchCall(ctx *parser.SearchCallContext) any {
|
||||
r.rewritten.WriteString(ctx.GetText())
|
||||
return nil
|
||||
}
|
||||
|
||||
// VisitFunctionCall visits function calls.
|
||||
func (r *WhereClauseRewriter) VisitFunctionCall(ctx *parser.FunctionCallContext) interface{} {
|
||||
func (r *WhereClauseRewriter) VisitFunctionCall(ctx *parser.FunctionCallContext) any {
|
||||
// Write function name
|
||||
if ctx.HAS() != nil {
|
||||
r.rewritten.WriteString("has")
|
||||
@@ -386,7 +395,7 @@ func (r *WhereClauseRewriter) VisitFunctionCall(ctx *parser.FunctionCallContext)
|
||||
}
|
||||
|
||||
// VisitFunctionParamList visits function parameter lists.
|
||||
func (r *WhereClauseRewriter) VisitFunctionParamList(ctx *parser.FunctionParamListContext) interface{} {
|
||||
func (r *WhereClauseRewriter) VisitFunctionParamList(ctx *parser.FunctionParamListContext) any {
|
||||
params := ctx.AllFunctionParam()
|
||||
for i, param := range params {
|
||||
if i > 0 {
|
||||
@@ -398,7 +407,7 @@ func (r *WhereClauseRewriter) VisitFunctionParamList(ctx *parser.FunctionParamLi
|
||||
}
|
||||
|
||||
// VisitFunctionParam visits function parameters.
|
||||
func (r *WhereClauseRewriter) VisitFunctionParam(ctx *parser.FunctionParamContext) interface{} {
|
||||
func (r *WhereClauseRewriter) VisitFunctionParam(ctx *parser.FunctionParamContext) any {
|
||||
if ctx.Key() != nil {
|
||||
ctx.Key().Accept(r)
|
||||
} else if ctx.Value() != nil {
|
||||
@@ -410,7 +419,7 @@ func (r *WhereClauseRewriter) VisitFunctionParam(ctx *parser.FunctionParamContex
|
||||
}
|
||||
|
||||
// VisitArray visits array expressions.
|
||||
func (r *WhereClauseRewriter) VisitArray(ctx *parser.ArrayContext) interface{} {
|
||||
func (r *WhereClauseRewriter) VisitArray(ctx *parser.ArrayContext) any {
|
||||
r.rewritten.WriteString("[")
|
||||
if ctx.ValueList() != nil {
|
||||
ctx.ValueList().Accept(r)
|
||||
@@ -420,13 +429,13 @@ func (r *WhereClauseRewriter) VisitArray(ctx *parser.ArrayContext) interface{} {
|
||||
}
|
||||
|
||||
// VisitValue visits value expressions.
|
||||
func (r *WhereClauseRewriter) VisitValue(ctx *parser.ValueContext) interface{} {
|
||||
func (r *WhereClauseRewriter) VisitValue(ctx *parser.ValueContext) any {
|
||||
r.rewritten.WriteString(ctx.GetText())
|
||||
return nil
|
||||
}
|
||||
|
||||
// VisitKey visits key expressions.
|
||||
func (r *WhereClauseRewriter) VisitKey(ctx *parser.KeyContext) interface{} {
|
||||
func (r *WhereClauseRewriter) VisitKey(ctx *parser.KeyContext) any {
|
||||
r.keysSeen[ctx.GetText()] = struct{}{}
|
||||
r.rewritten.WriteString(ctx.GetText())
|
||||
return nil
|
||||
|
||||
@@ -238,7 +238,7 @@
|
||||
}
|
||||
},
|
||||
"tags": [],
|
||||
"title": "Signoz GCP Memorystory Redis overview",
|
||||
"title": "Signoz GCP Memorystore Redis overview",
|
||||
"uploadedGrafana": false,
|
||||
"uuid": "019f85e9-3846-7dc9-9bce-b626b8a3eaff",
|
||||
"variables": {
|
||||
@@ -262,7 +262,7 @@
|
||||
"type": "DYNAMIC"
|
||||
},
|
||||
"dabcf41a-4121-4a03-8738-927576cc90bf": {
|
||||
"allSelected": true,
|
||||
"allSelected": false,
|
||||
"customValue": "",
|
||||
"defaultValue": "",
|
||||
"description": "GCP Project ID",
|
||||
@@ -390,7 +390,7 @@
|
||||
"disabled": false,
|
||||
"legend": "",
|
||||
"name": "A",
|
||||
"query": "rate({\"redis.googleapis.com/server/uptime\", project_id=\"$project_id\"}[5m])"
|
||||
"query": ""
|
||||
}
|
||||
],
|
||||
"queryType": "builder",
|
||||
|
||||
@@ -10,16 +10,14 @@ import (
|
||||
)
|
||||
|
||||
// buildClusterRecords assembles the page records. Node condition counts and
|
||||
// pod phase counts come from the respective per-group maps in both modes;
|
||||
// every row is a group of nodes+pods, so there's no per-row "current state"
|
||||
// concept (analogous to namespaces).
|
||||
// pod status counts come from the respective per-group maps in both modes;
|
||||
// every row is a group of nodes+pods (analogous to namespaces).
|
||||
func buildClusterRecords(
|
||||
resp *qbtypes.QueryRangeResponse,
|
||||
pageGroups []map[string]string,
|
||||
groupBy []qbtypes.GroupByKey,
|
||||
metadataMap map[string]map[string]string,
|
||||
nodeConditionCountsMap map[string]nodeConditionCounts,
|
||||
podPhaseCountsMap map[string]podPhaseCounts,
|
||||
podStatusCounts map[string]podStatusCounts,
|
||||
resourceCounts map[string]map[string]int64,
|
||||
) []inframonitoringtypes.ClusterRecord {
|
||||
@@ -61,16 +59,6 @@ func buildClusterRecords(
|
||||
}
|
||||
}
|
||||
|
||||
if phaseCountsForGroup, ok := podPhaseCountsMap[compositeKey]; ok {
|
||||
record.PodCountsByPhase = inframonitoringtypes.PodCountsByPhase{
|
||||
Pending: phaseCountsForGroup.Pending,
|
||||
Running: phaseCountsForGroup.Running,
|
||||
Succeeded: phaseCountsForGroup.Succeeded,
|
||||
Failed: phaseCountsForGroup.Failed,
|
||||
Unknown: phaseCountsForGroup.Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
if podStatusCountsForGroup, ok := podStatusCounts[compositeKey]; ok {
|
||||
record.PodCountsByStatus = podStatusCountsToResponse(podStatusCountsForGroup)
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ var clusterNameGroupByKey = qbtypes.GroupByKey{
|
||||
// Includes k8s.node.condition_ready and k8s.pod.phase so the response
|
||||
// short-circuits cleanly when a cluster doesn't ship those metrics — even
|
||||
// though they aren't part of the QB composite query (they're queried separately
|
||||
// via getPerGroupNodeConditionCounts and getPerGroupPodPhaseCounts).
|
||||
// via getPerGroupNodeConditionCounts and getPerGroupPodStatusCounts).
|
||||
var clustersTableMetricNamesList = []string{
|
||||
"k8s.node.cpu.usage",
|
||||
"k8s.node.allocatable_cpu",
|
||||
@@ -98,9 +98,9 @@ var orderByToClustersQueryNames = map[string][]string{
|
||||
|
||||
// newClustersTableListQuery builds the composite QB v5 request for the clusters list.
|
||||
// Cluster-scope metrics are derived by summing per-node metrics within the
|
||||
// group (default group: k8s.cluster.name). Node condition counts and pod phase
|
||||
// group (default group: k8s.cluster.name). Node condition counts and pod status
|
||||
// counts are derived separately via getPerGroupNodeConditionCounts and
|
||||
// getPerGroupPodPhaseCounts respectively (works for both list and grouped_list
|
||||
// getPerGroupPodStatusCounts respectively (works for both list and grouped_list
|
||||
// modes), so neither is included here. Query letters A/B/C/D mirror the v1
|
||||
// implementation and the v2 nodes list.
|
||||
func (m *module) newClustersTableListQuery() *qbtypes.QueryRangeRequest {
|
||||
|
||||
@@ -9,16 +9,14 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
// buildDaemonSetRecords assembles the page records. Pod phase counts come from
|
||||
// phaseCounts in both modes; every row is a group of pods (one daemonset in
|
||||
// list mode, an arbitrary roll-up in grouped_list mode), so there's no
|
||||
// per-row "current phase" concept.
|
||||
// buildDaemonSetRecords assembles the page records. Pod status counts come from
|
||||
// podStatusCounts in both modes; every row is a group of pods (one daemonset in
|
||||
// list mode, an arbitrary roll-up in grouped_list mode).
|
||||
func buildDaemonSetRecords(
|
||||
resp *qbtypes.QueryRangeResponse,
|
||||
pageGroups []map[string]string,
|
||||
groupBy []qbtypes.GroupByKey,
|
||||
metadataMap map[string]map[string]string,
|
||||
phaseCounts map[string]podPhaseCounts,
|
||||
podStatusCounts map[string]podStatusCounts,
|
||||
) []inframonitoringtypes.DaemonSetRecord {
|
||||
metricsMap := parseFullQueryResponse(resp, groupBy)
|
||||
@@ -76,16 +74,6 @@ func buildDaemonSetRecords(
|
||||
}
|
||||
}
|
||||
|
||||
if phaseCountsForGroup, ok := phaseCounts[compositeKey]; ok {
|
||||
record.PodCountsByPhase = inframonitoringtypes.PodCountsByPhase{
|
||||
Pending: phaseCountsForGroup.Pending,
|
||||
Running: phaseCountsForGroup.Running,
|
||||
Succeeded: phaseCountsForGroup.Succeeded,
|
||||
Failed: phaseCountsForGroup.Failed,
|
||||
Unknown: phaseCountsForGroup.Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
if podStatusCountsForGroup, ok := podStatusCounts[compositeKey]; ok {
|
||||
record.PodCountsByStatus = podStatusCountsToResponse(podStatusCountsForGroup)
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ var daemonSetNameGroupByKey = qbtypes.GroupByKey{
|
||||
|
||||
// daemonSetsTableMetricNamesList drives the existence/retention check.
|
||||
// Includes k8s.pod.phase even though phase isn't part of the QB composite query —
|
||||
// it is queried separately via getPerGroupPodPhaseCounts, and we want the
|
||||
// it is queried separately via getPerGroupPodStatusCounts, and we want the
|
||||
// response to short-circuit cleanly when the phase metric is absent.
|
||||
var daemonSetsTableMetricNamesList = []string{
|
||||
"k8s.pod.phase",
|
||||
|
||||
@@ -9,16 +9,14 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
// buildDeploymentRecords assembles the page records. Pod phase counts come from
|
||||
// phaseCounts in both modes; every row is a group of pods (one deployment in
|
||||
// list mode, an arbitrary roll-up in grouped_list mode), so there's no
|
||||
// per-row "current phase" concept.
|
||||
// buildDeploymentRecords assembles the page records. Pod status counts come from
|
||||
// podStatusCounts in both modes; every row is a group of pods (one deployment in
|
||||
// list mode, an arbitrary roll-up in grouped_list mode).
|
||||
func buildDeploymentRecords(
|
||||
resp *qbtypes.QueryRangeResponse,
|
||||
pageGroups []map[string]string,
|
||||
groupBy []qbtypes.GroupByKey,
|
||||
metadataMap map[string]map[string]string,
|
||||
phaseCounts map[string]podPhaseCounts,
|
||||
podStatusCounts map[string]podStatusCounts,
|
||||
) []inframonitoringtypes.DeploymentRecord {
|
||||
metricsMap := parseFullQueryResponse(resp, groupBy)
|
||||
@@ -68,16 +66,6 @@ func buildDeploymentRecords(
|
||||
}
|
||||
}
|
||||
|
||||
if phaseCountsForGroup, ok := phaseCounts[compositeKey]; ok {
|
||||
record.PodCountsByPhase = inframonitoringtypes.PodCountsByPhase{
|
||||
Pending: phaseCountsForGroup.Pending,
|
||||
Running: phaseCountsForGroup.Running,
|
||||
Succeeded: phaseCountsForGroup.Succeeded,
|
||||
Failed: phaseCountsForGroup.Failed,
|
||||
Unknown: phaseCountsForGroup.Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
if podStatusCountsForGroup, ok := podStatusCounts[compositeKey]; ok {
|
||||
record.PodCountsByStatus = podStatusCountsToResponse(podStatusCountsForGroup)
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ var deploymentNameGroupByKey = qbtypes.GroupByKey{
|
||||
|
||||
// deploymentsTableMetricNamesList drives the existence/retention check.
|
||||
// Includes k8s.pod.phase even though phase isn't part of the QB composite query —
|
||||
// it is queried separately via getPerGroupPodPhaseCounts, and we want the
|
||||
// it is queried separately via getPerGroupPodStatusCounts, and we want the
|
||||
// response to short-circuit cleanly when the phase metric is absent.
|
||||
var deploymentsTableMetricNamesList = []string{
|
||||
"k8s.pod.phase",
|
||||
|
||||
@@ -17,15 +17,6 @@ type groupHostStatusCounts struct {
|
||||
Inactive int
|
||||
}
|
||||
|
||||
// podPhaseCounts holds per-group pod counts bucketed by latest phase in window.
|
||||
type podPhaseCounts struct {
|
||||
Pending int
|
||||
Running int
|
||||
Succeeded int
|
||||
Failed int
|
||||
Unknown int
|
||||
}
|
||||
|
||||
// podStatusCounts holds per-group pod counts bucketed by latest kubectl-style
|
||||
// display status in window. Mirrors inframonitoringtypes.PodCountsByStatus.
|
||||
type podStatusCounts struct {
|
||||
|
||||
@@ -9,16 +9,14 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
// buildJobRecords assembles the page records. Pod phase counts come from
|
||||
// phaseCounts in both modes; every row is a group of pods (one job in
|
||||
// list mode, an arbitrary roll-up in grouped_list mode), so there's no
|
||||
// per-row "current phase" concept.
|
||||
// buildJobRecords assembles the page records. Pod status counts come from
|
||||
// podStatusCounts in both modes; every row is a group of pods (one job in
|
||||
// list mode, an arbitrary roll-up in grouped_list mode).
|
||||
func buildJobRecords(
|
||||
resp *qbtypes.QueryRangeResponse,
|
||||
pageGroups []map[string]string,
|
||||
groupBy []qbtypes.GroupByKey,
|
||||
metadataMap map[string]map[string]string,
|
||||
phaseCounts map[string]podPhaseCounts,
|
||||
podStatusCounts map[string]podStatusCounts,
|
||||
) []inframonitoringtypes.JobRecord {
|
||||
metricsMap := parseFullQueryResponse(resp, groupBy)
|
||||
@@ -76,16 +74,6 @@ func buildJobRecords(
|
||||
}
|
||||
}
|
||||
|
||||
if phaseCountsForGroup, ok := phaseCounts[compositeKey]; ok {
|
||||
record.PodCountsByPhase = inframonitoringtypes.PodCountsByPhase{
|
||||
Pending: phaseCountsForGroup.Pending,
|
||||
Running: phaseCountsForGroup.Running,
|
||||
Succeeded: phaseCountsForGroup.Succeeded,
|
||||
Failed: phaseCountsForGroup.Failed,
|
||||
Unknown: phaseCountsForGroup.Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
if podStatusCountsForGroup, ok := podStatusCounts[compositeKey]; ok {
|
||||
record.PodCountsByStatus = podStatusCountsToResponse(podStatusCountsForGroup)
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ var jobNameGroupByKey = qbtypes.GroupByKey{
|
||||
|
||||
// jobsTableMetricNamesList drives the existence/retention check.
|
||||
// Includes k8s.pod.phase even though phase isn't part of the QB composite query —
|
||||
// it is queried separately via getPerGroupPodPhaseCounts, and we want the
|
||||
// it is queried separately via getPerGroupPodStatusCounts, and we want the
|
||||
// response to short-circuit cleanly when the phase metric is absent.
|
||||
var jobsTableMetricNamesList = []string{
|
||||
"k8s.pod.phase",
|
||||
|
||||
@@ -317,7 +317,6 @@ func (m *module) ListPods(ctx context.Context, orgID valuer.UUID, req *inframoni
|
||||
|
||||
var (
|
||||
queryResp *qbtypes.QueryRangeResponse
|
||||
phaseCounts map[string]podPhaseCounts
|
||||
statusCounts map[string]podStatusCounts
|
||||
statusWarning *qbtypes.QueryWarnData
|
||||
restartCounts map[string]int64
|
||||
@@ -330,11 +329,6 @@ func (m *module) ListPods(ctx context.Context, orgID valuer.UUID, req *inframoni
|
||||
queryResp, err = m.querier.QueryRange(gCtx, orgID, fullQueryReq)
|
||||
return err
|
||||
})
|
||||
g.Go(func() error {
|
||||
var err error
|
||||
phaseCounts, err = m.getPerGroupPodPhaseCounts(gCtx, orgID, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
|
||||
return err
|
||||
})
|
||||
g.Go(func() error {
|
||||
var err error
|
||||
statusCounts, statusWarning, err = m.getPerGroupPodStatusCountsWithReqMetricChecks(gCtx, orgID, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
|
||||
@@ -351,7 +345,7 @@ func (m *module) ListPods(ctx context.Context, orgID valuer.UUID, req *inframoni
|
||||
}
|
||||
|
||||
isPodUIDInGroupBy := isKeyInGroupByAttrs(req.GroupBy, podUIDAttrKey)
|
||||
resp.Records = buildPodRecords(isPodUIDInGroupBy, queryResp, pageGroups, req.GroupBy, metadataMap, phaseCounts, statusCounts, restartCounts, req.End)
|
||||
resp.Records = buildPodRecords(isPodUIDInGroupBy, queryResp, pageGroups, req.GroupBy, metadataMap, statusCounts, restartCounts, req.End)
|
||||
resp.Warning = mergeQueryWarnings(queryResp.Warning, statusWarning)
|
||||
|
||||
return resp, nil
|
||||
@@ -526,7 +520,6 @@ func (m *module) ListNodes(ctx context.Context, orgID valuer.UUID, req *inframon
|
||||
var (
|
||||
queryResp *qbtypes.QueryRangeResponse
|
||||
nodeConditionCounts map[string]nodeConditionCounts
|
||||
podPhaseCounts map[string]podPhaseCounts
|
||||
podStatusCounts map[string]podStatusCounts
|
||||
podStatusWarning *qbtypes.QueryWarnData
|
||||
)
|
||||
@@ -543,11 +536,6 @@ func (m *module) ListNodes(ctx context.Context, orgID valuer.UUID, req *inframon
|
||||
nodeConditionCounts, err = m.getPerGroupNodeConditionCounts(gCtx, orgID, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
|
||||
return err
|
||||
})
|
||||
g.Go(func() error {
|
||||
var err error
|
||||
podPhaseCounts, err = m.getPerGroupPodPhaseCounts(gCtx, orgID, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
|
||||
return err
|
||||
})
|
||||
g.Go(func() error {
|
||||
var err error
|
||||
podStatusCounts, podStatusWarning, err = m.getPerGroupPodStatusCountsWithReqMetricChecks(gCtx, orgID, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
|
||||
@@ -559,7 +547,7 @@ func (m *module) ListNodes(ctx context.Context, orgID valuer.UUID, req *inframon
|
||||
}
|
||||
|
||||
isNodeNameInGroupBy := isKeyInGroupByAttrs(req.GroupBy, inframonitoringtypes.NodeNameAttrKey)
|
||||
resp.Records = buildNodeRecords(isNodeNameInGroupBy, queryResp, pageGroups, req.GroupBy, metadataMap, nodeConditionCounts, podPhaseCounts, podStatusCounts)
|
||||
resp.Records = buildNodeRecords(isNodeNameInGroupBy, queryResp, pageGroups, req.GroupBy, metadataMap, nodeConditionCounts, podStatusCounts)
|
||||
resp.Warning = mergeQueryWarnings(queryResp.Warning, podStatusWarning)
|
||||
|
||||
return resp, nil
|
||||
@@ -629,7 +617,6 @@ func (m *module) ListNamespaces(ctx context.Context, orgID valuer.UUID, req *inf
|
||||
|
||||
var (
|
||||
queryResp *qbtypes.QueryRangeResponse
|
||||
phaseCounts map[string]podPhaseCounts
|
||||
podStatusCounts map[string]podStatusCounts
|
||||
podStatusWarning *qbtypes.QueryWarnData
|
||||
resourceCounts map[string]map[string]int64
|
||||
@@ -642,11 +629,6 @@ func (m *module) ListNamespaces(ctx context.Context, orgID valuer.UUID, req *inf
|
||||
queryResp, err = m.querier.QueryRange(gCtx, orgID, fullQueryReq)
|
||||
return err
|
||||
})
|
||||
g.Go(func() error {
|
||||
var err error
|
||||
phaseCounts, err = m.getPerGroupPodPhaseCounts(gCtx, orgID, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
|
||||
return err
|
||||
})
|
||||
g.Go(func() error {
|
||||
var err error
|
||||
podStatusCounts, podStatusWarning, err = m.getPerGroupPodStatusCountsWithReqMetricChecks(gCtx, orgID, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
|
||||
@@ -662,7 +644,7 @@ func (m *module) ListNamespaces(ctx context.Context, orgID valuer.UUID, req *inf
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp.Records = buildNamespaceRecords(queryResp, pageGroups, req.GroupBy, metadataMap, phaseCounts, podStatusCounts, resourceCounts)
|
||||
resp.Records = buildNamespaceRecords(queryResp, pageGroups, req.GroupBy, metadataMap, podStatusCounts, resourceCounts)
|
||||
resp.Warning = mergeQueryWarnings(queryResp.Warning, podStatusWarning)
|
||||
|
||||
return resp, nil
|
||||
@@ -735,7 +717,6 @@ func (m *module) ListClusters(ctx context.Context, orgID valuer.UUID, req *infra
|
||||
var (
|
||||
queryResp *qbtypes.QueryRangeResponse
|
||||
nodeConditionCountsMap map[string]nodeConditionCounts
|
||||
podPhaseCountsMap map[string]podPhaseCounts
|
||||
podStatusCounts map[string]podStatusCounts
|
||||
podStatusWarning *qbtypes.QueryWarnData
|
||||
resourceCounts map[string]map[string]int64
|
||||
@@ -753,11 +734,6 @@ func (m *module) ListClusters(ctx context.Context, orgID valuer.UUID, req *infra
|
||||
nodeConditionCountsMap, err = m.getPerGroupNodeConditionCounts(gCtx, orgID, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
|
||||
return err
|
||||
})
|
||||
g.Go(func() error {
|
||||
var err error
|
||||
podPhaseCountsMap, err = m.getPerGroupPodPhaseCounts(gCtx, orgID, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
|
||||
return err
|
||||
})
|
||||
g.Go(func() error {
|
||||
var err error
|
||||
podStatusCounts, podStatusWarning, err = m.getPerGroupPodStatusCountsWithReqMetricChecks(gCtx, orgID, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
|
||||
@@ -773,7 +749,7 @@ func (m *module) ListClusters(ctx context.Context, orgID valuer.UUID, req *infra
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp.Records = buildClusterRecords(queryResp, pageGroups, req.GroupBy, metadataMap, nodeConditionCountsMap, podPhaseCountsMap, podStatusCounts, resourceCounts)
|
||||
resp.Records = buildClusterRecords(queryResp, pageGroups, req.GroupBy, metadataMap, nodeConditionCountsMap, podStatusCounts, resourceCounts)
|
||||
resp.Warning = mergeQueryWarnings(queryResp.Warning, podStatusWarning)
|
||||
|
||||
return resp, nil
|
||||
@@ -927,7 +903,6 @@ func (m *module) ListDeployments(ctx context.Context, orgID valuer.UUID, req *in
|
||||
|
||||
var (
|
||||
queryResp *qbtypes.QueryRangeResponse
|
||||
phaseCounts map[string]podPhaseCounts
|
||||
podStatusCounts map[string]podStatusCounts
|
||||
podStatusWarning *qbtypes.QueryWarnData
|
||||
)
|
||||
@@ -939,11 +914,6 @@ func (m *module) ListDeployments(ctx context.Context, orgID valuer.UUID, req *in
|
||||
queryResp, err = m.querier.QueryRange(gCtx, orgID, fullQueryReq)
|
||||
return err
|
||||
})
|
||||
g.Go(func() error {
|
||||
var err error
|
||||
phaseCounts, err = m.getPerGroupPodPhaseCounts(gCtx, orgID, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
|
||||
return err
|
||||
})
|
||||
g.Go(func() error {
|
||||
var err error
|
||||
podStatusCounts, podStatusWarning, err = m.getPerGroupPodStatusCountsWithReqMetricChecks(gCtx, orgID, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
|
||||
@@ -954,7 +924,7 @@ func (m *module) ListDeployments(ctx context.Context, orgID valuer.UUID, req *in
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp.Records = buildDeploymentRecords(queryResp, pageGroups, req.GroupBy, metadataMap, phaseCounts, podStatusCounts)
|
||||
resp.Records = buildDeploymentRecords(queryResp, pageGroups, req.GroupBy, metadataMap, podStatusCounts)
|
||||
resp.Warning = mergeQueryWarnings(queryResp.Warning, podStatusWarning)
|
||||
|
||||
return resp, nil
|
||||
@@ -1029,10 +999,9 @@ func (m *module) ListStatefulSets(ctx context.Context, orgID valuer.UUID, req *i
|
||||
fullQueryReq := buildFullQueryRequest(req.Start, req.End, filterExpr, req.GroupBy, pageGroups, m.newStatefulSetsTableListQuery())
|
||||
|
||||
// Pods owned by a StatefulSet carry k8s.statefulset.name as a resource attribute,
|
||||
// so default-groupBy gives per-statefulset phase counts automatically.
|
||||
// so default-groupBy gives per-statefulset status counts automatically.
|
||||
var (
|
||||
queryResp *qbtypes.QueryRangeResponse
|
||||
phaseCounts map[string]podPhaseCounts
|
||||
podStatusCounts map[string]podStatusCounts
|
||||
podStatusWarning *qbtypes.QueryWarnData
|
||||
)
|
||||
@@ -1044,11 +1013,6 @@ func (m *module) ListStatefulSets(ctx context.Context, orgID valuer.UUID, req *i
|
||||
queryResp, err = m.querier.QueryRange(gCtx, orgID, fullQueryReq)
|
||||
return err
|
||||
})
|
||||
g.Go(func() error {
|
||||
var err error
|
||||
phaseCounts, err = m.getPerGroupPodPhaseCounts(gCtx, orgID, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
|
||||
return err
|
||||
})
|
||||
g.Go(func() error {
|
||||
var err error
|
||||
podStatusCounts, podStatusWarning, err = m.getPerGroupPodStatusCountsWithReqMetricChecks(gCtx, orgID, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
|
||||
@@ -1059,7 +1023,7 @@ func (m *module) ListStatefulSets(ctx context.Context, orgID valuer.UUID, req *i
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp.Records = buildStatefulSetRecords(queryResp, pageGroups, req.GroupBy, metadataMap, phaseCounts, podStatusCounts)
|
||||
resp.Records = buildStatefulSetRecords(queryResp, pageGroups, req.GroupBy, metadataMap, podStatusCounts)
|
||||
resp.Warning = mergeQueryWarnings(queryResp.Warning, podStatusWarning)
|
||||
|
||||
return resp, nil
|
||||
@@ -1134,10 +1098,9 @@ func (m *module) ListJobs(ctx context.Context, orgID valuer.UUID, req *inframoni
|
||||
fullQueryReq := buildFullQueryRequest(req.Start, req.End, filterExpr, req.GroupBy, pageGroups, m.newJobsTableListQuery())
|
||||
|
||||
// Pods owned by a Job carry k8s.job.name as a resource attribute, so default-groupBy
|
||||
// gives per-job phase counts automatically.
|
||||
// gives per-job status counts automatically.
|
||||
var (
|
||||
queryResp *qbtypes.QueryRangeResponse
|
||||
phaseCounts map[string]podPhaseCounts
|
||||
podStatusCounts map[string]podStatusCounts
|
||||
podStatusWarning *qbtypes.QueryWarnData
|
||||
)
|
||||
@@ -1149,11 +1112,6 @@ func (m *module) ListJobs(ctx context.Context, orgID valuer.UUID, req *inframoni
|
||||
queryResp, err = m.querier.QueryRange(gCtx, orgID, fullQueryReq)
|
||||
return err
|
||||
})
|
||||
g.Go(func() error {
|
||||
var err error
|
||||
phaseCounts, err = m.getPerGroupPodPhaseCounts(gCtx, orgID, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
|
||||
return err
|
||||
})
|
||||
g.Go(func() error {
|
||||
var err error
|
||||
podStatusCounts, podStatusWarning, err = m.getPerGroupPodStatusCountsWithReqMetricChecks(gCtx, orgID, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
|
||||
@@ -1164,7 +1122,7 @@ func (m *module) ListJobs(ctx context.Context, orgID valuer.UUID, req *inframoni
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp.Records = buildJobRecords(queryResp, pageGroups, req.GroupBy, metadataMap, phaseCounts, podStatusCounts)
|
||||
resp.Records = buildJobRecords(queryResp, pageGroups, req.GroupBy, metadataMap, podStatusCounts)
|
||||
resp.Warning = mergeQueryWarnings(queryResp.Warning, podStatusWarning)
|
||||
|
||||
return resp, nil
|
||||
@@ -1239,10 +1197,9 @@ func (m *module) ListDaemonSets(ctx context.Context, orgID valuer.UUID, req *inf
|
||||
fullQueryReq := buildFullQueryRequest(req.Start, req.End, filterExpr, req.GroupBy, pageGroups, m.newDaemonSetsTableListQuery())
|
||||
|
||||
// Pods owned by a DaemonSet carry k8s.daemonset.name as a resource attribute,
|
||||
// so default-groupBy gives per-daemonset phase counts automatically.
|
||||
// so default-groupBy gives per-daemonset status counts automatically.
|
||||
var (
|
||||
queryResp *qbtypes.QueryRangeResponse
|
||||
phaseCounts map[string]podPhaseCounts
|
||||
podStatusCounts map[string]podStatusCounts
|
||||
podStatusWarning *qbtypes.QueryWarnData
|
||||
)
|
||||
@@ -1254,11 +1211,6 @@ func (m *module) ListDaemonSets(ctx context.Context, orgID valuer.UUID, req *inf
|
||||
queryResp, err = m.querier.QueryRange(gCtx, orgID, fullQueryReq)
|
||||
return err
|
||||
})
|
||||
g.Go(func() error {
|
||||
var err error
|
||||
phaseCounts, err = m.getPerGroupPodPhaseCounts(gCtx, orgID, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
|
||||
return err
|
||||
})
|
||||
g.Go(func() error {
|
||||
var err error
|
||||
podStatusCounts, podStatusWarning, err = m.getPerGroupPodStatusCountsWithReqMetricChecks(gCtx, orgID, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
|
||||
@@ -1269,7 +1221,7 @@ func (m *module) ListDaemonSets(ctx context.Context, orgID valuer.UUID, req *inf
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp.Records = buildDaemonSetRecords(queryResp, pageGroups, req.GroupBy, metadataMap, phaseCounts, podStatusCounts)
|
||||
resp.Records = buildDaemonSetRecords(queryResp, pageGroups, req.GroupBy, metadataMap, podStatusCounts)
|
||||
resp.Warning = mergeQueryWarnings(queryResp.Warning, podStatusWarning)
|
||||
|
||||
return resp, nil
|
||||
|
||||
@@ -9,15 +9,13 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
// buildNamespaceRecords assembles the page records. Pod phase counts come from
|
||||
// phaseCounts in both modes; every row is a group of pods, so there's no
|
||||
// per-row "current phase" concept (unlike pods/nodes list mode).
|
||||
// buildNamespaceRecords assembles the page records. Pod status counts come from
|
||||
// podStatusCounts in both modes; every row is a group of pods.
|
||||
func buildNamespaceRecords(
|
||||
resp *qbtypes.QueryRangeResponse,
|
||||
pageGroups []map[string]string,
|
||||
groupBy []qbtypes.GroupByKey,
|
||||
metadataMap map[string]map[string]string,
|
||||
phaseCounts map[string]podPhaseCounts,
|
||||
podStatusCounts map[string]podStatusCounts,
|
||||
resourceCounts map[string]map[string]int64,
|
||||
) []inframonitoringtypes.NamespaceRecord {
|
||||
@@ -44,16 +42,6 @@ func buildNamespaceRecords(
|
||||
}
|
||||
}
|
||||
|
||||
if phaseCountsForGroup, ok := phaseCounts[compositeKey]; ok {
|
||||
record.PodCountsByPhase = inframonitoringtypes.PodCountsByPhase{
|
||||
Pending: phaseCountsForGroup.Pending,
|
||||
Running: phaseCountsForGroup.Running,
|
||||
Succeeded: phaseCountsForGroup.Succeeded,
|
||||
Failed: phaseCountsForGroup.Failed,
|
||||
Unknown: phaseCountsForGroup.Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
if podStatusCountsForGroup, ok := podStatusCounts[compositeKey]; ok {
|
||||
record.PodCountsByStatus = podStatusCountsToResponse(podStatusCountsForGroup)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ var namespaceNameGroupByKey = qbtypes.GroupByKey{
|
||||
// namespacesTableMetricNamesList drives the existence/retention check.
|
||||
// Includes k8s.pod.phase so the response short-circuits cleanly when a
|
||||
// cluster doesn't ship the metric — even though phase isn't part of the
|
||||
// QB composite query (it's queried separately via getPerGroupPodPhaseCounts).
|
||||
// QB composite query (it's queried separately via getPerGroupPodStatusCounts).
|
||||
var namespacesTableMetricNamesList = []string{
|
||||
"k8s.pod.cpu.usage",
|
||||
"k8s.pod.memory.working_set",
|
||||
@@ -80,8 +80,8 @@ var orderByToNamespacesQueryNames = map[string][]string{
|
||||
}
|
||||
|
||||
// newNamespacesTableListQuery builds the composite QB v5 request for the namespaces list.
|
||||
// Pod phase counts are derived separately via getPerGroupPodPhaseCounts (works for both
|
||||
// list and grouped_list modes), so no phase query is included here.
|
||||
// Pod status counts are derived separately via getPerGroupPodStatusCounts (works for both
|
||||
// list and grouped_list modes), so no status query is included here.
|
||||
// Query letters A and D are kept aligned with the v1 implementation.
|
||||
func (m *module) newNamespacesTableListQuery() *qbtypes.QueryRangeRequest {
|
||||
queries := []qbtypes.QueryEnvelope{
|
||||
|
||||
@@ -25,7 +25,6 @@ func buildNodeRecords(
|
||||
groupBy []qbtypes.GroupByKey,
|
||||
metadataMap map[string]map[string]string,
|
||||
nodeConditionCounts map[string]nodeConditionCounts,
|
||||
podPhaseCounts map[string]podPhaseCounts,
|
||||
podStatusCounts map[string]podStatusCounts,
|
||||
) []inframonitoringtypes.NodeRecord {
|
||||
metricsMap := parseFullQueryResponse(resp, groupBy)
|
||||
@@ -77,16 +76,6 @@ func buildNodeRecords(
|
||||
}
|
||||
}
|
||||
|
||||
if podPhaseCountsForGroup, ok := podPhaseCounts[compositeKey]; ok {
|
||||
record.PodCountsByPhase = inframonitoringtypes.PodCountsByPhase{
|
||||
Pending: podPhaseCountsForGroup.Pending,
|
||||
Running: podPhaseCountsForGroup.Running,
|
||||
Succeeded: podPhaseCountsForGroup.Succeeded,
|
||||
Failed: podPhaseCountsForGroup.Failed,
|
||||
Unknown: podPhaseCountsForGroup.Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
if podStatusCountsForGroup, ok := podStatusCounts[compositeKey]; ok {
|
||||
record.PodCountsByStatus = podStatusCountsToResponse(podStatusCountsForGroup)
|
||||
}
|
||||
|
||||
@@ -15,17 +15,16 @@ import (
|
||||
"github.com/huandu/go-sqlbuilder"
|
||||
)
|
||||
|
||||
// buildPodRecords assembles the page records. Phase counts come from
|
||||
// phaseCounts in both modes. In list mode (isPodUIDInGroupBy=true) each
|
||||
// group is one pod, so exactly one count is 1; PodPhase is derived from
|
||||
// which one. In grouped_list mode PodPhase stays PodPhaseNoData.
|
||||
// buildPodRecords assembles the page records. Status counts come from
|
||||
// statusCounts in both modes. In list mode (isPodUIDInGroupBy=true) each
|
||||
// group is one pod, so exactly one count is 1; PodStatus is derived from
|
||||
// which one. In grouped_list mode PodStatus stays PodStatusNoData.
|
||||
func buildPodRecords(
|
||||
isPodUIDInGroupBy bool,
|
||||
resp *qbtypes.QueryRangeResponse,
|
||||
pageGroups []map[string]string,
|
||||
groupBy []qbtypes.GroupByKey,
|
||||
metadataMap map[string]map[string]string,
|
||||
phaseCounts map[string]podPhaseCounts,
|
||||
statusCounts map[string]podStatusCounts,
|
||||
restartCounts map[string]int64,
|
||||
reqEnd int64,
|
||||
@@ -39,7 +38,6 @@ func buildPodRecords(
|
||||
|
||||
record := inframonitoringtypes.PodRecord{ // initialize with default values
|
||||
PodUID: podUID,
|
||||
PodPhase: inframonitoringtypes.PodPhaseNoData,
|
||||
PodStatus: inframonitoringtypes.PodStatusNoData,
|
||||
PodRestarts: -1,
|
||||
PodCPU: -1,
|
||||
@@ -73,32 +71,6 @@ func buildPodRecords(
|
||||
}
|
||||
}
|
||||
|
||||
if phaseCountsForGroup, ok := phaseCounts[compositeKey]; ok {
|
||||
record.PodCountsByPhase = inframonitoringtypes.PodCountsByPhase{
|
||||
Pending: phaseCountsForGroup.Pending,
|
||||
Running: phaseCountsForGroup.Running,
|
||||
Succeeded: phaseCountsForGroup.Succeeded,
|
||||
Failed: phaseCountsForGroup.Failed,
|
||||
Unknown: phaseCountsForGroup.Unknown,
|
||||
}
|
||||
|
||||
// In list mode each group is one pod; the count==1 bucket identifies the phase.
|
||||
if isPodUIDInGroupBy {
|
||||
switch {
|
||||
case phaseCountsForGroup.Pending == 1:
|
||||
record.PodPhase = inframonitoringtypes.PodPhasePending
|
||||
case phaseCountsForGroup.Running == 1:
|
||||
record.PodPhase = inframonitoringtypes.PodPhaseRunning
|
||||
case phaseCountsForGroup.Succeeded == 1:
|
||||
record.PodPhase = inframonitoringtypes.PodPhaseSucceeded
|
||||
case phaseCountsForGroup.Failed == 1:
|
||||
record.PodPhase = inframonitoringtypes.PodPhaseFailed
|
||||
case phaseCountsForGroup.Unknown == 1:
|
||||
record.PodPhase = inframonitoringtypes.PodPhaseUnknown
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if statusCountsForGroup, ok := statusCounts[compositeKey]; ok {
|
||||
record.PodCountsByStatus = podStatusCountsToResponse(statusCountsForGroup)
|
||||
|
||||
@@ -235,162 +207,6 @@ func (m *module) getPodsTableMetadata(ctx context.Context, orgID valuer.UUID, re
|
||||
return m.getMetadata(ctx, orgID, podsTableMetricNamesList, req.GroupBy, nonGroupByAttrs, req.Filter, req.Start, req.End)
|
||||
}
|
||||
|
||||
// getPerGroupPodPhaseCounts computes per-group pod counts bucketed by each
|
||||
// pod's latest phase in the requested window.
|
||||
// Pipeline:
|
||||
//
|
||||
// timeSeriesFPs: fp ↔ (pod_uid, groupBy cols) from the time_series table.
|
||||
// User filter + page-groups filter applied here.
|
||||
// latestPhasePerPod: INNER JOIN samples × timeSeriesFPs, collapsed to
|
||||
// the latest phase per pod via argMax(value, unix_milli).
|
||||
// countPodsPerPhase: per-group uniqExactIf into 5 phase buckets.
|
||||
//
|
||||
// Groups absent from the result map have implicit zero counts (caller default).
|
||||
func (m *module) getPerGroupPodPhaseCounts(
|
||||
ctx context.Context,
|
||||
orgID valuer.UUID,
|
||||
start, end int64,
|
||||
filter *qbtypes.Filter,
|
||||
groupBy []qbtypes.GroupByKey,
|
||||
pageGroups []map[string]string,
|
||||
) (map[string]podPhaseCounts, error) {
|
||||
if len(pageGroups) == 0 || len(groupBy) == 0 {
|
||||
return map[string]podPhaseCounts{}, nil
|
||||
}
|
||||
|
||||
// Merge user filter with page-groups IN clauses.
|
||||
userFilterExpr := ""
|
||||
if filter != nil {
|
||||
userFilterExpr = filter.Expression
|
||||
}
|
||||
pageGroupsFilterExpr := buildPageGroupsFilterExpr(pageGroups)
|
||||
mergedFilterExpr := mergeFilterExpressions(userFilterExpr, pageGroupsFilterExpr)
|
||||
|
||||
// Step-floor bounds + resolve tables in one shot to match QB v5 querier.
|
||||
samplesStartMs, flooredEndMs, tsAdjustedStart, _, localTimeSeriesTable, distributedSamplesTable, _ := alignedMetricWindow(start, end)
|
||||
valueCol := telemetrymetrics.ValueColumnForSamplesTable(distributedSamplesTable)
|
||||
|
||||
// ----- timeSeriesFPs -----
|
||||
timeSeriesFPs := sqlbuilder.NewSelectBuilder()
|
||||
timeSeriesFPsSelectCols := []string{
|
||||
"fingerprint",
|
||||
fmt.Sprintf("JSONExtractString(labels, %s) AS pod_uid", timeSeriesFPs.Var(podUIDAttrKey)),
|
||||
}
|
||||
for _, key := range groupBy {
|
||||
timeSeriesFPsSelectCols = append(timeSeriesFPsSelectCols,
|
||||
fmt.Sprintf("JSONExtractString(labels, %s) AS %s", timeSeriesFPs.Var(key.Name), quoteIdentifier(key.Name)),
|
||||
)
|
||||
}
|
||||
timeSeriesFPs.Select(timeSeriesFPsSelectCols...)
|
||||
timeSeriesFPs.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, localTimeSeriesTable))
|
||||
timeSeriesFPs.Where(
|
||||
timeSeriesFPs.E("metric_name", podPhaseMetricName),
|
||||
timeSeriesFPs.GE("unix_milli", tsAdjustedStart),
|
||||
timeSeriesFPs.LE("unix_milli", flooredEndMs),
|
||||
)
|
||||
if mergedFilterExpr != "" {
|
||||
filterClause, err := m.buildFilterClause(ctx, orgID, &qbtypes.Filter{Expression: mergedFilterExpr}, start, end)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if filterClause != nil {
|
||||
timeSeriesFPs.AddWhereClause(filterClause)
|
||||
}
|
||||
}
|
||||
timeSeriesFPsGroupBy := []string{"fingerprint", "pod_uid"}
|
||||
for _, key := range groupBy {
|
||||
timeSeriesFPsGroupBy = append(timeSeriesFPsGroupBy, quoteIdentifier(key.Name))
|
||||
}
|
||||
timeSeriesFPs.GroupBy(timeSeriesFPsGroupBy...)
|
||||
timeSeriesFPsSQL, timeSeriesFPsArgs := timeSeriesFPs.BuildWithFlavor(sqlbuilder.ClickHouse)
|
||||
|
||||
latestPhasePerPod := sqlbuilder.NewSelectBuilder()
|
||||
latestPhasePerPodSelectCols := []string{"tsfp.pod_uid AS pod_uid"}
|
||||
latestPhasePerPodGroupBy := []string{"pod_uid"}
|
||||
for _, key := range groupBy {
|
||||
col := quoteIdentifier(key.Name)
|
||||
latestPhasePerPodSelectCols = append(latestPhasePerPodSelectCols, fmt.Sprintf("tsfp.%s AS %s", col, col))
|
||||
latestPhasePerPodGroupBy = append(latestPhasePerPodGroupBy, col)
|
||||
}
|
||||
latestPhasePerPodSelectCols = append(latestPhasePerPodSelectCols,
|
||||
fmt.Sprintf("argMax(samples.%s, samples.unix_milli) AS phase_value", valueCol),
|
||||
)
|
||||
latestPhasePerPod.Select(latestPhasePerPodSelectCols...)
|
||||
latestPhasePerPod.From(fmt.Sprintf(
|
||||
"%s.%s AS samples INNER JOIN time_series_fps AS tsfp ON samples.fingerprint = tsfp.fingerprint",
|
||||
telemetrymetrics.DBName, distributedSamplesTable,
|
||||
))
|
||||
latestPhasePerPod.Where(
|
||||
latestPhasePerPod.E("samples.metric_name", podPhaseMetricName),
|
||||
latestPhasePerPod.GE("samples.unix_milli", samplesStartMs),
|
||||
latestPhasePerPod.L("samples.unix_milli", flooredEndMs),
|
||||
"tsfp.pod_uid != ''",
|
||||
)
|
||||
latestPhasePerPod.GroupBy(latestPhasePerPodGroupBy...)
|
||||
latestPhasePerPodSQL, latestPhasePerPodArgs := latestPhasePerPod.BuildWithFlavor(sqlbuilder.ClickHouse)
|
||||
|
||||
// ----- countPodsPerPhase (outer SELECT) -----
|
||||
countPodsPerPhaseSelectCols := make([]string, 0, len(groupBy)+5)
|
||||
countPodsPerPhaseGroupBy := make([]string, 0, len(groupBy))
|
||||
for _, key := range groupBy {
|
||||
col := quoteIdentifier(key.Name)
|
||||
countPodsPerPhaseSelectCols = append(countPodsPerPhaseSelectCols, col)
|
||||
countPodsPerPhaseGroupBy = append(countPodsPerPhaseGroupBy, col)
|
||||
}
|
||||
countPodsPerPhaseSelectCols = append(countPodsPerPhaseSelectCols,
|
||||
fmt.Sprintf("uniqExactIf(pod_uid, phase_value = %d) AS pending_count", inframonitoringtypes.PodPhaseNumPending),
|
||||
fmt.Sprintf("uniqExactIf(pod_uid, phase_value = %d) AS running_count", inframonitoringtypes.PodPhaseNumRunning),
|
||||
fmt.Sprintf("uniqExactIf(pod_uid, phase_value = %d) AS succeeded_count", inframonitoringtypes.PodPhaseNumSucceeded),
|
||||
fmt.Sprintf("uniqExactIf(pod_uid, phase_value = %d) AS failed_count", inframonitoringtypes.PodPhaseNumFailed),
|
||||
fmt.Sprintf("uniqExactIf(pod_uid, phase_value = %d) AS unknown_count", inframonitoringtypes.PodPhaseNumUnknown),
|
||||
)
|
||||
countPodsPerPhaseSQL := fmt.Sprintf(
|
||||
"SELECT %s FROM latest_phase_per_pod GROUP BY %s",
|
||||
strings.Join(countPodsPerPhaseSelectCols, ", "),
|
||||
strings.Join(countPodsPerPhaseGroupBy, ", "),
|
||||
)
|
||||
|
||||
// Combine CTEs + outer.
|
||||
cteFragments := []string{
|
||||
fmt.Sprintf("time_series_fps AS (%s)", timeSeriesFPsSQL),
|
||||
fmt.Sprintf("latest_phase_per_pod AS (%s)", latestPhasePerPodSQL),
|
||||
}
|
||||
finalSQL := querybuilder.CombineCTEs(cteFragments) + countPodsPerPhaseSQL
|
||||
finalArgs := querybuilder.PrependArgs([][]any{timeSeriesFPsArgs, latestPhasePerPodArgs}, nil)
|
||||
|
||||
rows, err := m.telemetryStore.ClickhouseDB().Query(ctx, finalSQL, finalArgs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
result := make(map[string]podPhaseCounts)
|
||||
for rows.Next() {
|
||||
groupVals := make([]string, len(groupBy))
|
||||
scanPtrs := make([]any, 0, len(groupBy)+5)
|
||||
for i := range groupVals {
|
||||
scanPtrs = append(scanPtrs, &groupVals[i])
|
||||
}
|
||||
var pending, running, succeeded, failed, unknown uint64
|
||||
scanPtrs = append(scanPtrs, &pending, &running, &succeeded, &failed, &unknown)
|
||||
|
||||
if err := rows.Scan(scanPtrs...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[compositeKeyFromList(groupVals)] = podPhaseCounts{
|
||||
Pending: int(pending),
|
||||
Running: int(running),
|
||||
Succeeded: int(succeeded),
|
||||
Failed: int(failed),
|
||||
Unknown: int(unknown),
|
||||
}
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// getPerGroupPodStatusCountsWithReqMetricChecks gates getPerGroupPodStatusCounts
|
||||
// on the required metrics being present. If any of podStatusMetricNamesList has
|
||||
// never been reported, it skips the query and returns a warning instead (the
|
||||
@@ -438,7 +254,7 @@ func (m *module) getPerGroupPodStatusCountsWithReqMetricChecks(
|
||||
// getPerGroupPodStatusCounts computes per-group pod counts bucketed by each
|
||||
// pod's latest kubectl-style display status in the requested window. Caller
|
||||
// must ensure the required metrics exist (getPerGroupPodStatusCountsWithReqMetricChecks).
|
||||
// Pipeline (mirrors getPerGroupPodPhaseCounts, more CTEs):
|
||||
// Pipeline:
|
||||
//
|
||||
// phase_fps / phase_per_pod: latest k8s.pod.phase per pod (+ groupBy cols).
|
||||
// pod_reason_fps / pod_reason_per_pod: latest k8s.pod.status_reason per pod.
|
||||
|
||||
@@ -69,8 +69,8 @@ var orderByToPodsQueryNames = map[string][]string{
|
||||
}
|
||||
|
||||
// newPodsTableListQuery builds the composite QB v5 request for the pods list.
|
||||
// Pod phase is derived separately via getPerGroupPodPhaseCounts (works for both
|
||||
// list and grouped_list modes), so no phase query is included here.
|
||||
// Pod status is derived separately via getPerGroupPodStatusCounts (works for both
|
||||
// list and grouped_list modes), so no status query is included here.
|
||||
func (m *module) newPodsTableListQuery() *qbtypes.QueryRangeRequest {
|
||||
queries := []qbtypes.QueryEnvelope{
|
||||
// Query A: CPU usage
|
||||
|
||||
@@ -9,16 +9,14 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
// buildStatefulSetRecords assembles the page records. Pod phase counts come from
|
||||
// phaseCounts in both modes; every row is a group of pods (one statefulset in
|
||||
// list mode, an arbitrary roll-up in grouped_list mode), so there's no
|
||||
// per-row "current phase" concept.
|
||||
// buildStatefulSetRecords assembles the page records. Pod status counts come from
|
||||
// podStatusCounts in both modes; every row is a group of pods (one statefulset in
|
||||
// list mode, an arbitrary roll-up in grouped_list mode).
|
||||
func buildStatefulSetRecords(
|
||||
resp *qbtypes.QueryRangeResponse,
|
||||
pageGroups []map[string]string,
|
||||
groupBy []qbtypes.GroupByKey,
|
||||
metadataMap map[string]map[string]string,
|
||||
phaseCounts map[string]podPhaseCounts,
|
||||
podStatusCounts map[string]podStatusCounts,
|
||||
) []inframonitoringtypes.StatefulSetRecord {
|
||||
metricsMap := parseFullQueryResponse(resp, groupBy)
|
||||
@@ -68,16 +66,6 @@ func buildStatefulSetRecords(
|
||||
}
|
||||
}
|
||||
|
||||
if phaseCountsForGroup, ok := phaseCounts[compositeKey]; ok {
|
||||
record.PodCountsByPhase = inframonitoringtypes.PodCountsByPhase{
|
||||
Pending: phaseCountsForGroup.Pending,
|
||||
Running: phaseCountsForGroup.Running,
|
||||
Succeeded: phaseCountsForGroup.Succeeded,
|
||||
Failed: phaseCountsForGroup.Failed,
|
||||
Unknown: phaseCountsForGroup.Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
if podStatusCountsForGroup, ok := podStatusCounts[compositeKey]; ok {
|
||||
record.PodCountsByStatus = podStatusCountsToResponse(podStatusCountsForGroup)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user