mirror of
https://github.com/SigNoz/signoz.git
synced 2026-07-24 23:10:39 +01:00
Compare commits
2 Commits
nv/sql-das
...
b3-search
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbea7d8263 | ||
|
|
6f6e289b82 |
@@ -1592,6 +1592,13 @@ components:
|
||||
required:
|
||||
- config
|
||||
type: object
|
||||
CommonDisplay:
|
||||
properties:
|
||||
description:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
type: object
|
||||
CommonJSONRef:
|
||||
properties:
|
||||
$ref:
|
||||
@@ -2725,6 +2732,11 @@ components:
|
||||
type: object
|
||||
DashboardtypesDashboardSpec:
|
||||
properties:
|
||||
datasources:
|
||||
additionalProperties:
|
||||
$ref: '#/components/schemas/DashboardtypesDatasourceSpec'
|
||||
nullable: true
|
||||
type: object
|
||||
display:
|
||||
$ref: '#/components/schemas/DashboardtypesDisplay'
|
||||
duration:
|
||||
@@ -2789,6 +2801,39 @@ components:
|
||||
required:
|
||||
- version
|
||||
type: object
|
||||
DashboardtypesDatasourcePlugin:
|
||||
discriminator:
|
||||
mapping:
|
||||
signoz/Datasource: '#/components/schemas/DashboardtypesDatasourcePluginVariantGithubComSigNozSignozPkgTypesDashboardtypesSigNozDatasourceSpec'
|
||||
propertyName: kind
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/DashboardtypesDatasourcePluginVariantGithubComSigNozSignozPkgTypesDashboardtypesSigNozDatasourceSpec'
|
||||
type: object
|
||||
DashboardtypesDatasourcePluginKind:
|
||||
enum:
|
||||
- signoz/Datasource
|
||||
type: string
|
||||
DashboardtypesDatasourcePluginVariantGithubComSigNozSignozPkgTypesDashboardtypesSigNozDatasourceSpec:
|
||||
properties:
|
||||
kind:
|
||||
enum:
|
||||
- signoz/Datasource
|
||||
type: string
|
||||
spec:
|
||||
$ref: '#/components/schemas/DashboardtypesSigNozDatasourceSpec'
|
||||
required:
|
||||
- kind
|
||||
- spec
|
||||
type: object
|
||||
DashboardtypesDatasourceSpec:
|
||||
properties:
|
||||
default:
|
||||
type: boolean
|
||||
display:
|
||||
$ref: '#/components/schemas/CommonDisplay'
|
||||
plugin:
|
||||
$ref: '#/components/schemas/DashboardtypesDatasourcePlugin'
|
||||
type: object
|
||||
DashboardtypesDisplay:
|
||||
properties:
|
||||
description:
|
||||
@@ -2798,22 +2843,14 @@ components:
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
DashboardtypesDynamicVariableSignal:
|
||||
enum:
|
||||
- traces
|
||||
- logs
|
||||
- metrics
|
||||
- all
|
||||
type: string
|
||||
DashboardtypesDynamicVariableSpec:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
signal:
|
||||
$ref: '#/components/schemas/DashboardtypesDynamicVariableSignal'
|
||||
$ref: '#/components/schemas/TelemetrytypesSignal'
|
||||
required:
|
||||
- name
|
||||
- signal
|
||||
type: object
|
||||
DashboardtypesFillMode:
|
||||
enum:
|
||||
@@ -3565,6 +3602,8 @@ components:
|
||||
required:
|
||||
- queryValue
|
||||
type: object
|
||||
DashboardtypesSigNozDatasourceSpec:
|
||||
type: object
|
||||
DashboardtypesSource:
|
||||
enum:
|
||||
- user
|
||||
@@ -4260,6 +4299,8 @@ components:
|
||||
type: object
|
||||
nodeCountsByReadiness:
|
||||
$ref: '#/components/schemas/InframonitoringtypesNodeCountsByReadiness'
|
||||
podCountsByPhase:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
|
||||
podCountsByStatus:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
|
||||
required:
|
||||
@@ -4269,6 +4310,7 @@ components:
|
||||
- clusterMemory
|
||||
- clusterMemoryAllocatable
|
||||
- nodeCountsByReadiness
|
||||
- podCountsByPhase
|
||||
- podCountsByStatus
|
||||
- counts
|
||||
- meta
|
||||
@@ -4478,6 +4520,8 @@ components:
|
||||
type: object
|
||||
misscheduledNodes:
|
||||
type: integer
|
||||
podCountsByPhase:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
|
||||
podCountsByStatus:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
|
||||
readyNodes:
|
||||
@@ -4494,6 +4538,7 @@ components:
|
||||
- currentNodes
|
||||
- readyNodes
|
||||
- misscheduledNodes
|
||||
- podCountsByPhase
|
||||
- podCountsByStatus
|
||||
- meta
|
||||
type: object
|
||||
@@ -4548,6 +4593,8 @@ components:
|
||||
type: string
|
||||
nullable: true
|
||||
type: object
|
||||
podCountsByPhase:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
|
||||
podCountsByStatus:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
|
||||
required:
|
||||
@@ -4560,6 +4607,7 @@ components:
|
||||
- deploymentMemoryLimit
|
||||
- desiredPods
|
||||
- availablePods
|
||||
- podCountsByPhase
|
||||
- podCountsByStatus
|
||||
- meta
|
||||
type: object
|
||||
@@ -4691,6 +4739,8 @@ components:
|
||||
type: string
|
||||
nullable: true
|
||||
type: object
|
||||
podCountsByPhase:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
|
||||
podCountsByStatus:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
|
||||
successfulPods:
|
||||
@@ -4707,6 +4757,7 @@ components:
|
||||
- activePods
|
||||
- failedPods
|
||||
- successfulPods
|
||||
- podCountsByPhase
|
||||
- podCountsByStatus
|
||||
- meta
|
||||
type: object
|
||||
@@ -4816,12 +4867,15 @@ components:
|
||||
type: number
|
||||
namespaceName:
|
||||
type: string
|
||||
podCountsByPhase:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
|
||||
podCountsByStatus:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
|
||||
required:
|
||||
- namespaceName
|
||||
- namespaceCPU
|
||||
- namespaceMemory
|
||||
- podCountsByPhase
|
||||
- podCountsByStatus
|
||||
- counts
|
||||
- meta
|
||||
@@ -4887,12 +4941,15 @@ components:
|
||||
type: number
|
||||
nodeName:
|
||||
type: string
|
||||
podCountsByPhase:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
|
||||
podCountsByStatus:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
|
||||
required:
|
||||
- nodeName
|
||||
- condition
|
||||
- nodeCountsByReadiness
|
||||
- podCountsByPhase
|
||||
- podCountsByStatus
|
||||
- nodeCPU
|
||||
- nodeCPUAllocatable
|
||||
@@ -4920,6 +4977,25 @@ 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:
|
||||
@@ -4978,6 +5054,15 @@ components:
|
||||
- shutdown
|
||||
- unexpectedAdmissionError
|
||||
type: object
|
||||
InframonitoringtypesPodPhase:
|
||||
enum:
|
||||
- pending
|
||||
- running
|
||||
- succeeded
|
||||
- failed
|
||||
- unknown
|
||||
- no_data
|
||||
type: string
|
||||
InframonitoringtypesPodRecord:
|
||||
properties:
|
||||
meta:
|
||||
@@ -4997,6 +5082,8 @@ components:
|
||||
podCPURequest:
|
||||
format: double
|
||||
type: number
|
||||
podCountsByPhase:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
|
||||
podCountsByStatus:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
|
||||
podMemory:
|
||||
@@ -5008,6 +5095,8 @@ components:
|
||||
podMemoryRequest:
|
||||
format: double
|
||||
type: number
|
||||
podPhase:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodPhase'
|
||||
podRestarts:
|
||||
format: int64
|
||||
type: integer
|
||||
@@ -5023,6 +5112,8 @@ components:
|
||||
- podMemory
|
||||
- podMemoryRequest
|
||||
- podMemoryLimit
|
||||
- podPhase
|
||||
- podCountsByPhase
|
||||
- podStatus
|
||||
- podCountsByStatus
|
||||
- podRestarts
|
||||
@@ -5373,6 +5464,8 @@ components:
|
||||
type: string
|
||||
nullable: true
|
||||
type: object
|
||||
podCountsByPhase:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
|
||||
podCountsByStatus:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
|
||||
statefulSetCPU:
|
||||
@@ -5405,6 +5498,7 @@ components:
|
||||
- statefulSetMemoryLimit
|
||||
- desiredPods
|
||||
- currentPods
|
||||
- podCountsByPhase
|
||||
- podCountsByStatus
|
||||
- meta
|
||||
type: object
|
||||
@@ -16058,19 +16152,17 @@ 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 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.'
|
||||
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.'
|
||||
operationId: ListClusters
|
||||
requestBody:
|
||||
content:
|
||||
@@ -16138,16 +16230,13 @@ 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 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
|
||||
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,
|
||||
@@ -16215,19 +16304,17 @@ 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 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,
|
||||
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.'
|
||||
@@ -16362,12 +16449,9 @@ 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 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).
|
||||
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
|
||||
@@ -16517,18 +16601,16 @@ 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 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.'
|
||||
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.'
|
||||
operationId: ListNamespaces
|
||||
requestBody:
|
||||
content:
|
||||
@@ -16588,21 +16670,18 @@ 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 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.'
|
||||
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.'
|
||||
operationId: ListNodes
|
||||
requestBody:
|
||||
content:
|
||||
@@ -16661,23 +16740,20 @@ 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 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,
|
||||
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 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.'
|
||||
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.'
|
||||
operationId: ListPods
|
||||
requestBody:
|
||||
content:
|
||||
@@ -16810,19 +16886,16 @@ 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
|
||||
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,
|
||||
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.'
|
||||
operationId: ListStatefulSets
|
||||
|
||||
@@ -272,10 +272,6 @@ func (module *module) CloneV2(ctx context.Context, orgID valuer.UUID, createdBy
|
||||
return module.pkgDashboardModule.CloneV2(ctx, orgID, createdBy, creator, id)
|
||||
}
|
||||
|
||||
func (module *module) ConvertAllV1ToV2(ctx context.Context, orgID valuer.UUID) (*dashboardtypes.V1ToV2MigrationResult, error) {
|
||||
return module.pkgDashboardModule.ConvertAllV1ToV2(ctx, orgID)
|
||||
}
|
||||
|
||||
func (module *module) GetV2(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*dashboardtypes.DashboardV2, error) {
|
||||
return module.pkgDashboardModule.GetV2(ctx, orgID, id)
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
"antd": "5.11.0",
|
||||
"antd-table-saveas-excel": "2.2.1",
|
||||
"antlr4": "4.13.2",
|
||||
"axios": "1.18.0",
|
||||
"axios": "1.16.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.12",
|
||||
"dompurify": "3.4.11",
|
||||
"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.35.0",
|
||||
"sharp": "0.34.5",
|
||||
"stylelint": "17.7.0",
|
||||
"svgo": "4.0.2",
|
||||
"svgo": "4.0.1",
|
||||
"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.18.0
|
||||
version: 1.18.0
|
||||
specifier: 1.16.0
|
||||
version: 1.16.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.12
|
||||
version: 3.4.12
|
||||
specifier: 3.4.11
|
||||
version: 3.4.11
|
||||
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.35.0
|
||||
version: 0.35.0
|
||||
specifier: 0.34.5
|
||||
version: 0.34.5
|
||||
stylelint:
|
||||
specifier: 17.7.0
|
||||
version: 17.7.0(typescript@5.9.3)
|
||||
svgo:
|
||||
specifier: 4.0.2
|
||||
version: 4.0.2
|
||||
specifier: 4.0.1
|
||||
version: 4.0.1
|
||||
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.35.0)(svgo@4.0.2)
|
||||
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)
|
||||
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,9 +1460,6 @@ 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==}
|
||||
|
||||
@@ -1717,165 +1714,156 @@ packages:
|
||||
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
|
||||
engines: {node: '>=18.18'}
|
||||
|
||||
'@img/colour@1.1.0':
|
||||
resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
|
||||
'@img/colour@1.0.0':
|
||||
resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@img/sharp-darwin-arm64@0.35.0':
|
||||
resolution: {integrity: sha512-ZgaYEwaj+lx/5n4W8GmZ2IYz0PQHjN5eqRcfijWGB+2Aq7ZInZGa0qJyAn6DEtyLuWHRSrmWOqT9q3qqTBvmUQ==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
'@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}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@img/sharp-darwin-x64@0.35.0':
|
||||
resolution: {integrity: sha512-c1z9LFpKB0slQW3RchwBE8iSVzGp70TNjUUO9k4BZwwW4HH7JBGHeIy4b+kk4n/kcBASb9evKCE3/7Slmslgiw==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
'@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}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@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==}
|
||||
'@img/sharp-libvips-darwin-arm64@1.2.4':
|
||||
resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@img/sharp-libvips-darwin-x64@1.3.0':
|
||||
resolution: {integrity: sha512-Pl2OmOvrJ42adUllESxBsG54PfXLo1OYg9i3c5/5Ln/qJ0gZuTM9YMhQJPIbXqwidLRc/c2zuHt4RsrymmNv7A==}
|
||||
'@img/sharp-libvips-darwin-x64@1.2.4':
|
||||
resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@img/sharp-libvips-linux-arm64@1.3.0':
|
||||
resolution: {integrity: sha512-C0SqjoFKnszqa44EQ7xoaT48nnO0lOyXEULfXMWi8krrjOPGYkeK30Okzla6ATbBYsyZ0ySinK0FVkpv3DwzfQ==}
|
||||
'@img/sharp-libvips-linux-arm64@1.2.4':
|
||||
resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-arm@1.3.0':
|
||||
resolution: {integrity: sha512-A8UpHoUDW4DwnXoV6+q3C1s7QLRAHtPDEjWuNZjwHMyoCNZnm0GeNN8ls9f/bsEYTRQRW96C/n34XJQHJ2fT7A==}
|
||||
'@img/sharp-libvips-linux-arm@1.2.4':
|
||||
resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-ppc64@1.3.0':
|
||||
resolution: {integrity: sha512-WOpkVxAjFd369iaIzEgNRreFD+gWdUMIGD5zplhNKNeqS6mm5dac3q2AFyCBmzYoAdouzZvRBgxy4z8QHZb4/A==}
|
||||
'@img/sharp-libvips-linux-ppc64@1.2.4':
|
||||
resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-riscv64@1.3.0':
|
||||
resolution: {integrity: sha512-DRWw0mOHusrCCuw2rqP87oLg6PGlkomVDFqw2hIwsSfwWpu4k3XLcBPaKKl6ct/GtL/cwNkgwjV/tc0Mqht3VA==}
|
||||
'@img/sharp-libvips-linux-riscv64@1.2.4':
|
||||
resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-s390x@1.3.0':
|
||||
resolution: {integrity: sha512-9APy+nFWhHS+kzLgWZfLcyrUd7YqnAQVa4BPOo4xkoHpdoktOAPG4cEr9+Jpl0TtqfVmcMJimNL5qNTyyOHZNA==}
|
||||
'@img/sharp-libvips-linux-s390x@1.2.4':
|
||||
resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-x64@1.3.0':
|
||||
resolution: {integrity: sha512-y9RNUYDe2A1UAdhLyfeOodGRszQdaEoe4nfOpp/sNVPl2CWIcUyFaDoCh4vPLPxu19803j2naLqZup2WxDXCLA==}
|
||||
'@img/sharp-libvips-linux-x64@1.2.4':
|
||||
resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-arm64@1.3.0':
|
||||
resolution: {integrity: sha512-cC1wkC0Mlucd0KSiGrLkJnB/ZqPvZCntc/Lk7ZnYO5ZSbF2euNek4Xvxafojq+wN1q/W0eprdpUIjUr/EV2PBg==}
|
||||
'@img/sharp-libvips-linuxmusl-arm64@1.2.4':
|
||||
resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-x64@1.3.0':
|
||||
resolution: {integrity: sha512-LiYMhUZicB1QG//+RvmYZpXJO8fYRENfp+MZUCnG9aw+AKvGAy9gPaCnuwsPcBFs8EV66M0NNxj9VHcNklE8zw==}
|
||||
'@img/sharp-libvips-linuxmusl-x64@1.2.4':
|
||||
resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-linux-arm64@0.35.0':
|
||||
resolution: {integrity: sha512-4+4XHLNT5wDT0roYlHTEmH9lDKt0acf9Tv+3hM3iceOirkxrR404/3WjAYZ9F9CkHrxeRcGLJXbi4vluMZ9O+A==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
'@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}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-arm@0.35.0':
|
||||
resolution: {integrity: sha512-VVlpEWwizEFIOom0zdoeKuO5nuTswzVE5uHcBNvHzmeHUpNFajY3HFfbQ+zIH4E2kVaZ/yVxmsShW56TtEy4uA==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
'@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}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-ppc64@0.35.0':
|
||||
resolution: {integrity: sha512-N3hzbEpUTJC8pWpPVJvgzGxM+so/MAXc8O2s/53B0LL9ZGpfXpME7Wizkc5d/8fRBlBtkDjzoZGDCqqNDHqLEw==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
'@img/sharp-linux-ppc64@0.34.5':
|
||||
resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-riscv64@0.35.0':
|
||||
resolution: {integrity: sha512-l6vmKVPnbS0RhVMbyxP5meAARsbhCnBN4fy31qz0+3a6Rv4jEqfzDrT89y6ZPkCi0AJGnwp2En528yXo401Hpw==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
'@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}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-s390x@0.35.0':
|
||||
resolution: {integrity: sha512-MYlMiPFiv/EKPAHnp3yNZ9AAWFsxga9c5Bkc6wkar6bqzHLlkGVJHRm0u1ei+VXnZxp3Mz9MG9ZIsI8vSOf3sQ==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
'@img/sharp-linux-s390x@0.34.5':
|
||||
resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-x64@0.35.0':
|
||||
resolution: {integrity: sha512-TYaItB5oj1ioXjhyn2xrR208vf+YuIIcHptQWRRaBmFhvIvL9D72DXN8w75xup0KXA8UdEAhQ9Qb2S49FD/9Cw==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
'@img/sharp-linux-x64@0.34.5':
|
||||
resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linuxmusl-arm64@0.35.0':
|
||||
resolution: {integrity: sha512-DSTb6ijQzqe6DdAaOBVqJ/SYf1vO8EW5bK6X6LRXufEBebf2722VCdvBUtZ3rtV0x2ApfPNDy/p7LrrjaWjiyQ==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
'@img/sharp-linuxmusl-arm64@0.34.5':
|
||||
resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-linuxmusl-x64@0.35.0':
|
||||
resolution: {integrity: sha512-K7ykQ+26Rt6+4BTU80AuGgTPIYX86UxiAKT4rcXX/WNTo7k1ZxpKz+TguHnwVpCqQK3B5PK0vZ0ZBe6nz/ib1w==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
'@img/sharp-linuxmusl-x64@0.34.5':
|
||||
resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@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'}
|
||||
'@img/sharp-wasm32@0.34.5':
|
||||
resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [wasm32]
|
||||
|
||||
'@img/sharp-win32-arm64@0.35.0':
|
||||
resolution: {integrity: sha512-M5eKxug0dabbaWgFKvPa3odNs2OpaP+81NASfGKkt4GcYXpNhSu7CaeYxWkLNV6vHmUp4hnCxnxrUyhUJhXbKA==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
'@img/sharp-win32-arm64@0.34.5':
|
||||
resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@img/sharp-win32-ia32@0.35.0':
|
||||
resolution: {integrity: sha512-z0+pZ03QCDvdVN0Ez9IX/yjWC19ikMlXrmdYMwYNLTh2BLPx3hXWPvyqWfquZ0BTO9O6GVOjIVoTcyyacMnWlQ==}
|
||||
engines: {node: ^20.9.0}
|
||||
'@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}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@img/sharp-win32-x64@0.35.0':
|
||||
resolution: {integrity: sha512-feNnlz5ZHKr0MY1LPHvZQyJeBkbo4ctsn0D8FvA53VTw5TC63rfEL2UrWbkSBR19htSE7Mw78xYVwdJqoMWVHw==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
'@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}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
@@ -4087,8 +4075,8 @@ packages:
|
||||
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
axios@1.18.0:
|
||||
resolution: {integrity: sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==}
|
||||
axios@1.16.0:
|
||||
resolution: {integrity: sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==}
|
||||
|
||||
babel-jest@29.6.4:
|
||||
resolution: {integrity: sha512-meLj23UlSLddj6PC+YTOFRgDAtjnZom8w/ACsrx0gtPtv5cJZk0A5Unk5bV4wixD7XaPCN1fQvpww8czkZURmw==}
|
||||
@@ -4893,8 +4881,8 @@ packages:
|
||||
resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
|
||||
engines: {node: '>= 4'}
|
||||
|
||||
dompurify@3.4.12:
|
||||
resolution: {integrity: sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg==}
|
||||
dompurify@3.4.11:
|
||||
resolution: {integrity: sha512-zhlUV12GsaRzMsf9q5M254YhA4+VuF0fG+QFqu6aYpoGlKtz+w8//jBcGVYBgQkR5GHjUomejY84AV+/uPbWdw==}
|
||||
|
||||
domutils@2.8.0:
|
||||
resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==}
|
||||
@@ -5460,6 +5448,10 @@ 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'}
|
||||
@@ -8070,6 +8062,10 @@ 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'}
|
||||
@@ -8126,9 +8122,9 @@ packages:
|
||||
shallowequal@1.1.0:
|
||||
resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==}
|
||||
|
||||
sharp@0.35.0:
|
||||
resolution: {integrity: sha512-BqvG5XbwPZ4NV0DK90d86leEECMsoa8bO0nqnKWlBDYxri4GJ7c4EDInaF6q20lTh/mATmnDIKWJFfXnoVfH5g==}
|
||||
engines: {node: '>=20.9.0'}
|
||||
sharp@0.34.5:
|
||||
resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
|
||||
shebang-command@2.0.0:
|
||||
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
|
||||
@@ -8380,8 +8376,8 @@ packages:
|
||||
svg-tags@1.0.0:
|
||||
resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==}
|
||||
|
||||
svgo@4.0.2:
|
||||
resolution: {integrity: sha512-ekx94z1rRc5LDi6oSUaeRnYhd0UOJxdtQCL2rF8xpWxD3TPAsISWOrxezqGovqS38GRZOdpDfvQe3ts6F7nsng==}
|
||||
svgo@4.0.1:
|
||||
resolution: {integrity: sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==}
|
||||
engines: {node: '>=16'}
|
||||
hasBin: true
|
||||
|
||||
@@ -10285,11 +10281,6 @@ 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
|
||||
@@ -10453,7 +10444,7 @@ snapshots:
|
||||
'@types/string-hash': 1.1.3
|
||||
d3-interpolate: 3.0.1
|
||||
date-fns: 4.1.0
|
||||
dompurify: 3.4.12
|
||||
dompurify: 3.4.11
|
||||
eventemitter3: 5.0.1
|
||||
fast_array_intersect: 1.1.0
|
||||
history: 4.10.1
|
||||
@@ -10494,110 +10485,100 @@ snapshots:
|
||||
|
||||
'@humanwhocodes/retry@0.4.3': {}
|
||||
|
||||
'@img/colour@1.1.0': {}
|
||||
'@img/colour@1.0.0': {}
|
||||
|
||||
'@img/sharp-darwin-arm64@0.35.0':
|
||||
'@img/sharp-darwin-arm64@0.34.5':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-darwin-arm64': 1.3.0
|
||||
'@img/sharp-libvips-darwin-arm64': 1.2.4
|
||||
optional: true
|
||||
|
||||
'@img/sharp-darwin-x64@0.35.0':
|
||||
'@img/sharp-darwin-x64@0.34.5':
|
||||
optionalDependencies:
|
||||
'@img/sharp-libvips-darwin-x64': 1.3.0
|
||||
'@img/sharp-libvips-darwin-x64': 1.2.4
|
||||
optional: true
|
||||
|
||||
'@img/sharp-freebsd-wasm32@0.35.0':
|
||||
'@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':
|
||||
dependencies:
|
||||
'@img/sharp-wasm32': 0.35.0
|
||||
'@emnapi/runtime': 1.8.1
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-darwin-arm64@1.3.0':
|
||||
'@img/sharp-win32-arm64@0.34.5':
|
||||
optional: true
|
||||
|
||||
'@img/sharp-libvips-darwin-x64@1.3.0':
|
||||
'@img/sharp-win32-ia32@0.34.5':
|
||||
optional: true
|
||||
|
||||
'@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':
|
||||
'@img/sharp-win32-x64@0.34.5':
|
||||
optional: true
|
||||
|
||||
'@isaacs/cliui@8.0.2':
|
||||
@@ -13002,15 +12983,13 @@ snapshots:
|
||||
dependencies:
|
||||
possible-typed-array-names: 1.1.0
|
||||
|
||||
axios@1.18.0:
|
||||
axios@1.16.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:
|
||||
@@ -13864,7 +13843,7 @@ snapshots:
|
||||
dependencies:
|
||||
domelementtype: 2.3.0
|
||||
|
||||
dompurify@3.4.12:
|
||||
dompurify@3.4.11:
|
||||
optionalDependencies:
|
||||
'@types/trusted-types': 2.0.7
|
||||
|
||||
@@ -14519,6 +14498,10 @@ 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
|
||||
@@ -14755,7 +14738,7 @@ snapshots:
|
||||
internal-slot@1.1.0:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
hasown: 2.0.4
|
||||
hasown: 2.0.2
|
||||
side-channel: 1.1.0
|
||||
|
||||
internmap@2.0.3: {}
|
||||
@@ -14809,7 +14792,7 @@ snapshots:
|
||||
|
||||
is-core-module@2.16.1:
|
||||
dependencies:
|
||||
hasown: 2.0.4
|
||||
hasown: 2.0.2
|
||||
|
||||
is-date-object@1.1.0:
|
||||
dependencies:
|
||||
@@ -14878,7 +14861,7 @@ snapshots:
|
||||
call-bound: 1.0.4
|
||||
gopd: 1.2.0
|
||||
has-tostringtag: 1.0.2
|
||||
hasown: 2.0.4
|
||||
hasown: 2.0.2
|
||||
|
||||
is-set@2.0.3: {}
|
||||
|
||||
@@ -16194,7 +16177,7 @@ snapshots:
|
||||
|
||||
monaco-editor@0.55.1:
|
||||
dependencies:
|
||||
dompurify: 3.4.12
|
||||
dompurify: 3.4.11
|
||||
marked: 14.0.0
|
||||
|
||||
motion-dom@11.18.1:
|
||||
@@ -16289,7 +16272,7 @@ snapshots:
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
iconv-lite: 0.6.3
|
||||
sax: 1.6.0
|
||||
sax: 1.4.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
optional: true
|
||||
@@ -17758,6 +17741,9 @@ snapshots:
|
||||
sax@1.3.0:
|
||||
optional: true
|
||||
|
||||
sax@1.4.4:
|
||||
optional: true
|
||||
|
||||
sax@1.6.0: {}
|
||||
|
||||
saxes@6.0.0:
|
||||
@@ -17811,37 +17797,36 @@ snapshots:
|
||||
|
||||
shallowequal@1.1.0: {}
|
||||
|
||||
sharp@0.35.0:
|
||||
sharp@0.34.5:
|
||||
dependencies:
|
||||
'@img/colour': 1.1.0
|
||||
'@img/colour': 1.0.0
|
||||
detect-libc: 2.1.2
|
||||
semver: 7.8.5
|
||||
optionalDependencies:
|
||||
'@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
|
||||
'@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
|
||||
|
||||
shebang-command@2.0.0:
|
||||
dependencies:
|
||||
@@ -18139,7 +18124,7 @@ snapshots:
|
||||
|
||||
svg-tags@1.0.0: {}
|
||||
|
||||
svgo@4.0.2:
|
||||
svgo@4.0.1:
|
||||
dependencies:
|
||||
commander: 11.1.0
|
||||
css-select: 5.2.2
|
||||
@@ -18606,14 +18591,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.35.0)(svgo@4.0.2):
|
||||
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):
|
||||
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.35.0
|
||||
svgo: 4.0.2
|
||||
sharp: 0.34.5
|
||||
svgo: 4.0.1
|
||||
|
||||
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 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.
|
||||
* 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.
|
||||
* @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 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.
|
||||
* 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.
|
||||
* @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 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.
|
||||
* 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.
|
||||
* @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 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.
|
||||
* 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.
|
||||
* @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 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.
|
||||
* 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.
|
||||
* @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 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.
|
||||
* 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.
|
||||
* @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 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.
|
||||
* 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.
|
||||
* @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 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.
|
||||
* 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.
|
||||
* @summary List StatefulSets for Infra Monitoring
|
||||
*/
|
||||
export const listStatefulSets = (
|
||||
|
||||
@@ -3236,6 +3236,17 @@ export interface CloudintegrationtypesUpdatableServiceDTO {
|
||||
config: CloudintegrationtypesServiceConfigDTO;
|
||||
}
|
||||
|
||||
export interface CommonDisplayDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export interface CommonJSONRefDTO {
|
||||
/**
|
||||
* @type string
|
||||
@@ -3979,6 +3990,44 @@ export interface DashboardtypesDashboardPanelRefDTO {
|
||||
panelName: string;
|
||||
}
|
||||
|
||||
export enum DashboardtypesDatasourcePluginVariantGithubComSigNozSignozPkgTypesDashboardtypesSigNozDatasourceSpecDTOKind {
|
||||
'signoz/Datasource' = 'signoz/Datasource',
|
||||
}
|
||||
export interface DashboardtypesSigNozDatasourceSpecDTO {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface DashboardtypesDatasourcePluginVariantGithubComSigNozSignozPkgTypesDashboardtypesSigNozDatasourceSpecDTO {
|
||||
/**
|
||||
* @enum signoz/Datasource
|
||||
* @type string
|
||||
*/
|
||||
kind: DashboardtypesDatasourcePluginVariantGithubComSigNozSignozPkgTypesDashboardtypesSigNozDatasourceSpecDTOKind;
|
||||
spec: DashboardtypesSigNozDatasourceSpecDTO;
|
||||
}
|
||||
|
||||
export type DashboardtypesDatasourcePluginDTO =
|
||||
DashboardtypesDatasourcePluginVariantGithubComSigNozSignozPkgTypesDashboardtypesSigNozDatasourceSpecDTO;
|
||||
|
||||
export interface DashboardtypesDatasourceSpecDTO {
|
||||
/**
|
||||
* @type boolean
|
||||
*/
|
||||
default?: boolean;
|
||||
display?: CommonDisplayDTO;
|
||||
plugin?: DashboardtypesDatasourcePluginDTO;
|
||||
}
|
||||
|
||||
export type DashboardtypesDashboardSpecDTODatasourcesAnyOf = {
|
||||
[key: string]: DashboardtypesDatasourceSpecDTO;
|
||||
};
|
||||
|
||||
/**
|
||||
* @nullable
|
||||
*/
|
||||
export type DashboardtypesDashboardSpecDTODatasources =
|
||||
DashboardtypesDashboardSpecDTODatasourcesAnyOf | null;
|
||||
|
||||
export enum DashboardtypesPanelKindDTO {
|
||||
Panel = 'Panel',
|
||||
}
|
||||
@@ -4619,18 +4668,12 @@ 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: DashboardtypesDynamicVariableSignalDTO;
|
||||
signal?: TelemetrytypesSignalDTO;
|
||||
}
|
||||
|
||||
export interface DashboardtypesVariablePluginVariantGithubComSigNozSignozPkgTypesDashboardtypesDynamicVariableSpecDTO {
|
||||
@@ -4758,6 +4801,10 @@ export type DashboardtypesVariableDTO =
|
||||
| DashboardtypesVariableEnvelopeGithubComSigNozSignozPkgTypesDashboardtypesTextVariableSpecDTO;
|
||||
|
||||
export interface DashboardtypesDashboardSpecDTO {
|
||||
/**
|
||||
* @type object,null
|
||||
*/
|
||||
datasources?: DashboardtypesDashboardSpecDTODatasources;
|
||||
display: DashboardtypesDisplayDTO;
|
||||
/**
|
||||
* @type string
|
||||
@@ -4833,6 +4880,9 @@ export interface DashboardtypesDashboardViewDTO {
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
export enum DashboardtypesDatasourcePluginKindDTO {
|
||||
'signoz/Datasource' = 'signoz/Datasource',
|
||||
}
|
||||
export interface TagtypesGettableTagDTO {
|
||||
/**
|
||||
* @type string
|
||||
@@ -5686,6 +5736,29 @@ 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
|
||||
@@ -5795,6 +5868,7 @@ export interface InframonitoringtypesClusterRecordDTO {
|
||||
*/
|
||||
meta: InframonitoringtypesClusterRecordDTOMeta;
|
||||
nodeCountsByReadiness: InframonitoringtypesNodeCountsByReadinessDTO;
|
||||
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
|
||||
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
|
||||
}
|
||||
|
||||
@@ -6070,6 +6144,7 @@ export interface InframonitoringtypesDaemonSetRecordDTO {
|
||||
* @type integer
|
||||
*/
|
||||
misscheduledNodes: number;
|
||||
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
|
||||
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -6151,6 +6226,7 @@ export interface InframonitoringtypesDeploymentRecordDTO {
|
||||
* @type object,null
|
||||
*/
|
||||
meta: InframonitoringtypesDeploymentRecordDTOMeta;
|
||||
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
|
||||
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
|
||||
}
|
||||
|
||||
@@ -6317,6 +6393,7 @@ export interface InframonitoringtypesJobRecordDTO {
|
||||
* @type object,null
|
||||
*/
|
||||
meta: InframonitoringtypesJobRecordDTOMeta;
|
||||
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
|
||||
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -6397,6 +6474,7 @@ export interface InframonitoringtypesNamespaceRecordDTO {
|
||||
* @type string
|
||||
*/
|
||||
namespaceName: string;
|
||||
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
|
||||
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
|
||||
}
|
||||
|
||||
@@ -6463,6 +6541,7 @@ export interface InframonitoringtypesNodeRecordDTO {
|
||||
* @type string
|
||||
*/
|
||||
nodeName: string;
|
||||
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
|
||||
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
|
||||
}
|
||||
|
||||
@@ -6483,6 +6562,14 @@ 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;
|
||||
};
|
||||
@@ -6539,6 +6626,7 @@ export interface InframonitoringtypesPodRecordDTO {
|
||||
* @format double
|
||||
*/
|
||||
podCPURequest: number;
|
||||
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
|
||||
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
|
||||
/**
|
||||
* @type number
|
||||
@@ -6555,6 +6643,7 @@ export interface InframonitoringtypesPodRecordDTO {
|
||||
* @format double
|
||||
*/
|
||||
podMemoryRequest: number;
|
||||
podPhase: InframonitoringtypesPodPhaseDTO;
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
@@ -6904,6 +6993,7 @@ export interface InframonitoringtypesStatefulSetRecordDTO {
|
||||
* @type object,null
|
||||
*/
|
||||
meta: InframonitoringtypesStatefulSetRecordDTOMeta;
|
||||
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
|
||||
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
|
||||
/**
|
||||
* @type number
|
||||
|
||||
@@ -1,50 +1,26 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError, AxiosResponse } from 'axios';
|
||||
import { AxiosError } 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 postExportRawData(props);
|
||||
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,
|
||||
},
|
||||
);
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw new Error(
|
||||
|
||||
@@ -713,19 +713,6 @@ const CustomMultiSelect: React.FC<CustomMultiSelectProps> = ({
|
||||
}
|
||||
};
|
||||
|
||||
// Row buttons select without letting the wrapping checkbox also toggle:
|
||||
// stop propagation, run the selection, then drop the active/chip focus.
|
||||
const selectFromButton = (
|
||||
e: React.MouseEvent,
|
||||
source: 'option' | 'checkbox',
|
||||
): void => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
handleItemSelection(source);
|
||||
setActiveChipIndex(-1);
|
||||
setActiveIndex(-1);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
key={option.value || `option-${index}`}
|
||||
@@ -739,6 +726,13 @@ const CustomMultiSelect: React.FC<CustomMultiSelectProps> = ({
|
||||
selected: isSelected,
|
||||
active: isActive,
|
||||
})}
|
||||
onClick={(e): void => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
handleItemSelection('option');
|
||||
setActiveChipIndex(-1);
|
||||
setActiveIndex(-1);
|
||||
}}
|
||||
onKeyDown={(e): void => {
|
||||
if ((e.key === 'Enter' || e.key === SPACEKEY) && isActive) {
|
||||
e.stopPropagation();
|
||||
@@ -758,7 +752,13 @@ const CustomMultiSelect: React.FC<CustomMultiSelectProps> = ({
|
||||
<Checkbox
|
||||
value={isSelected}
|
||||
className="option-checkbox"
|
||||
onClick={(e): void => selectFromButton(e, 'checkbox')}
|
||||
onClick={(e): void => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
handleItemSelection('checkbox');
|
||||
setActiveChipIndex(-1);
|
||||
setActiveIndex(-1);
|
||||
}}
|
||||
>
|
||||
<div className="option-content">
|
||||
<Typography.Text truncate={1} className="option-label-text">
|
||||
@@ -768,19 +768,11 @@ const CustomMultiSelect: React.FC<CustomMultiSelectProps> = ({
|
||||
<div className="option-badge">{capitalize(option.type)}</div>
|
||||
)}
|
||||
{option.value && ensureValidOption(option.value) && (
|
||||
<Button
|
||||
type="text"
|
||||
className="only-btn"
|
||||
onClick={(e): void => selectFromButton(e, 'option')}
|
||||
>
|
||||
<Button type="text" className="only-btn">
|
||||
{currentToggleTagValue({ option: option.value })}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
type="text"
|
||||
className="toggle-btn"
|
||||
onClick={(e): void => selectFromButton(e, 'checkbox')}
|
||||
>
|
||||
<Button type="text" className="toggle-btn">
|
||||
Toggle
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -656,28 +656,6 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('UI-03b: clicking "Only" selects just that value', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect
|
||||
options={mockOptions}
|
||||
onChange={mockOnChange}
|
||||
value={['frontend']}
|
||||
/>,
|
||||
);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
await user.click(combobox);
|
||||
|
||||
// "Only" renders for each non-selected row (hidden until hover via CSS,
|
||||
// which jsdom doesn't apply, so it's clickable here).
|
||||
const onlyButtons = await screen.findAllByText('Only');
|
||||
mockOnChange.mockClear();
|
||||
await user.click(onlyButtons[0]);
|
||||
|
||||
expect(mockOnChange).toHaveBeenCalledTimes(1);
|
||||
expect(mockOnChange.mock.calls[0][0]).toStrictEqual(['backend']);
|
||||
});
|
||||
|
||||
it('UI-04: Should display values with loading info at bottom', async () => {
|
||||
renderWithVirtuoso(
|
||||
<CustomMultiSelect options={mockOptions} onChange={mockOnChange} loading />,
|
||||
@@ -1471,7 +1449,7 @@ describe('CustomMultiSelect - Comprehensive Tests', () => {
|
||||
|
||||
expect(mockOnChange).toHaveBeenCalledWith(
|
||||
['custom-value'],
|
||||
[{ label: 'custom-value', value: 'custom-value', type: 'custom' }],
|
||||
[{ label: 'custom-value', value: 'custom-value' }],
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import { prioritizeOrAddOptionForMultiSelect } from '../utils';
|
||||
|
||||
describe('prioritizeOrAddOptionForMultiSelect ordering', () => {
|
||||
it('hoists selected then preserves the given (sorted) order in each group', () => {
|
||||
const sorted = ['apple', 'banana', 'cherry', 'date', 'elderberry'].map(
|
||||
(v) => ({ label: v, value: v }),
|
||||
);
|
||||
// selection given in a non-sorted order on purpose
|
||||
const result = prioritizeOrAddOptionForMultiSelect(sorted, [
|
||||
'date',
|
||||
'banana',
|
||||
]);
|
||||
expect(result.map((o) => o.value)).toStrictEqual([
|
||||
'banana',
|
||||
'date',
|
||||
'apple',
|
||||
'cherry',
|
||||
'elderberry',
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -458,9 +458,7 @@ $custom-border-color: #2c3044;
|
||||
|
||||
.option-item {
|
||||
padding: 8px 12px;
|
||||
// Not the whole row — only the checkbox and the action buttons get the
|
||||
// pointer (set below), so inert areas don't look clickable.
|
||||
cursor: default;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@@ -496,13 +494,6 @@ $custom-border-color: #2c3044;
|
||||
|
||||
.option-checkbox {
|
||||
width: 100%;
|
||||
cursor: default;
|
||||
|
||||
// The checkbox button is the only pointer target on the left; the label
|
||||
// still toggles on click but keeps a default cursor.
|
||||
> button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
// @signozhq/ui Checkbox renders children inside a <label> that is
|
||||
// content-sized by default. Make it fill the row (min-width: 0 lets it
|
||||
@@ -544,9 +535,9 @@ $custom-border-color: #2c3044;
|
||||
}
|
||||
}
|
||||
|
||||
// "Only"/"All" is the primary action — a filled pill that reads as a
|
||||
// button; "Toggle" is a secondary hint in plain text. Sized to the row's
|
||||
// resting height so revealing them on hover never shifts it.
|
||||
// Size the buttons to the row's resting content height (20px) and fully
|
||||
// override antd's default 32px Button box, so revealing them on hover
|
||||
// never changes the row height.
|
||||
.only-btn,
|
||||
.toggle-btn {
|
||||
display: none;
|
||||
@@ -554,39 +545,14 @@ $custom-border-color: #2c3044;
|
||||
justify-content: center;
|
||||
height: 18px;
|
||||
min-height: 0;
|
||||
padding: 0 6px;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.only-btn {
|
||||
padding: 4px 8px;
|
||||
// Black interior + a visible border so the pill stands out clearly
|
||||
// against the near-black row when revealed on hover.
|
||||
border: 1px solid var(--l3-border);
|
||||
border-radius: 3px;
|
||||
background-color: var(--bg-ink-500, #0b0c0e);
|
||||
color: var(--l1-foreground);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.toggle-btn {
|
||||
padding: 0 6px;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
color: var(--l2-foreground);
|
||||
cursor: pointer;
|
||||
}
|
||||
box-shadow: none;
|
||||
|
||||
// Toggle appears over the checkbox area; "Only/All" takes over the row
|
||||
// content and hides Toggle there (higher specificity wins).
|
||||
&:hover {
|
||||
.toggle-btn {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.option-badge {
|
||||
display: none;
|
||||
&:hover {
|
||||
background-color: unset;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -594,7 +560,6 @@ $custom-border-color: #2c3044;
|
||||
.only-btn {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.toggle-btn {
|
||||
display: none;
|
||||
}
|
||||
@@ -604,6 +569,15 @@ $custom-border-color: #2c3044;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.option-checkbox:hover {
|
||||
.toggle-btn {
|
||||
display: flex;
|
||||
}
|
||||
.option-badge {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loading-container {
|
||||
|
||||
@@ -9,7 +9,6 @@ import { extractQueryPairs } from 'utils/queryContextUtils';
|
||||
|
||||
import {
|
||||
convertAggregationToExpression,
|
||||
convertExpressionToFilters,
|
||||
convertFiltersToExpression,
|
||||
convertFiltersToExpressionWithExistingQuery,
|
||||
formatValueForExpression,
|
||||
@@ -1599,36 +1598,4 @@ 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,9 +176,7 @@ function formatSingleValueForFilter(
|
||||
}
|
||||
|
||||
if (isQuoted(value)) {
|
||||
// Unescape `\'` → `'` (inverse of formatSingleValue) so the round-trip doesn't
|
||||
// double the backslash each pass.
|
||||
return unquote(value).replace(/\\'/g, "'");
|
||||
return unquote(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -770,34 +768,6 @@ export const removeVariableFromExpression = (
|
||||
return removeKeysFromExpression(expression, keysToRemove, `$${variableName}`);
|
||||
};
|
||||
|
||||
// Appends `clause` as a top-level AND term, parenthesising the base only when it
|
||||
// has a top-level OR (AND binds tighter, so `a OR b AND c` would misbind).
|
||||
export const appendAndClause = (
|
||||
expression: string | undefined,
|
||||
clause: string,
|
||||
): string => {
|
||||
const base = expression?.trim();
|
||||
if (!base) {
|
||||
return clause;
|
||||
}
|
||||
|
||||
const chars = CharStreams.fromString(base);
|
||||
const lexer = new FilterQueryLexer(chars);
|
||||
lexer.removeErrorListeners();
|
||||
const tokenStream = new CommonTokenStream(lexer);
|
||||
const parser = new FilterQueryParser(tokenStream);
|
||||
parser.removeErrorListeners();
|
||||
const tree = parser.query();
|
||||
|
||||
if (parser.syntaxErrorsCount > 0) {
|
||||
return `(${base}) AND ${clause}`;
|
||||
}
|
||||
|
||||
const hasTopLevelOr =
|
||||
tree.expression().orExpression().andExpression_list().length > 1;
|
||||
return hasTopLevelOr ? `(${base}) AND ${clause}` : `${base} AND ${clause}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert old having format to new having format
|
||||
* @param having - Array of old having objects with columnName, op, and value
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
.static {
|
||||
// Tag chips are not interactive, but the @signozhq Badge darkens outline
|
||||
// variants on hover — which reads as clickable. Pin the hover background to the
|
||||
// resting background so hovering a plain tag produces no change.
|
||||
--badge-outline-hover-background-color: var(
|
||||
--badge-outline-background-color,
|
||||
color-mix(in oklab, var(--badge-background) 10%, transparent)
|
||||
);
|
||||
|
||||
cursor: default;
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
import { type MouseEvent, type ReactNode } from 'react';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import cx from 'classnames';
|
||||
|
||||
import styles from './TagBadge.module.scss';
|
||||
|
||||
interface TagBadgeProps {
|
||||
children: ReactNode;
|
||||
@@ -25,7 +22,7 @@ function TagBadge({
|
||||
<Badge
|
||||
color="sienna"
|
||||
variant="outline"
|
||||
className={cx(styles.static, className)}
|
||||
className={className}
|
||||
closable={closable}
|
||||
onClose={onClose}
|
||||
>
|
||||
|
||||
@@ -65,5 +65,4 @@
|
||||
min-width: 0;
|
||||
padding-left: 12px;
|
||||
padding-bottom: 12px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
@@ -25,52 +25,20 @@ describe('calculateChartDimensions', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('RIGHT: reserves a side column capped at 320px / 40% of the width and keeps full height', () => {
|
||||
it('RIGHT: reserves a side column capped at 30% of the width and keeps full height', () => {
|
||||
const dims = calculateChartDimensions({
|
||||
containerWidth: 1000,
|
||||
containerHeight: 400,
|
||||
legendConfig: { position: LegendPosition.RIGHT },
|
||||
seriesLabels: labels(10, 40),
|
||||
});
|
||||
expect(dims.legendWidth).toBe(320);
|
||||
expect(dims.width).toBe(680);
|
||||
// 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.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,12 +15,6 @@ 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.
|
||||
@@ -48,7 +42,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` fits the longest label, clamped to [150px, min(MAX_RIGHT_LEGEND_WIDTH, 40% width)].
|
||||
* - `legendWidth` is clamped between 150px and min(MAX_LEGEND_WIDTH, 30% of container width).
|
||||
* - Chart width is `containerWidth - legendWidth`.
|
||||
* - BOTTOM legend:
|
||||
* - Computes how many items fit per row, then uses at most 2 rows.
|
||||
@@ -86,22 +80,9 @@ export function calculateChartDimensions({
|
||||
const legendItemCount = seriesLabels.length;
|
||||
|
||||
if (legendConfig.position === LegendPosition.RIGHT) {
|
||||
// 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 maxRightLegendWidth = Math.min(MAX_LEGEND_WIDTH, containerWidth * 0.3);
|
||||
const rightLegendWidth = Math.min(
|
||||
Math.max(150, desiredLegendWidth),
|
||||
Math.max(150, approxLegendItemWidth),
|
||||
maxRightLegendWidth,
|
||||
);
|
||||
|
||||
|
||||
@@ -15,10 +15,6 @@
|
||||
|
||||
&--legend-right {
|
||||
flex-direction: row;
|
||||
|
||||
.chart-layout__legend-wrapper {
|
||||
padding-top: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&__legend-wrapper {
|
||||
|
||||
@@ -15,6 +15,7 @@ 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,
|
||||
@@ -28,6 +29,7 @@ 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 {
|
||||
@@ -91,6 +93,11 @@ 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);
|
||||
};
|
||||
@@ -183,8 +190,8 @@ function Hosts(): JSX.Element {
|
||||
|
||||
const getInitialLogTracesExpression = useCallback(
|
||||
(host: InframonitoringtypesHostRecordDTO) =>
|
||||
hostInitialLogTracesExpression(host),
|
||||
[],
|
||||
hostInitialLogTracesExpression(host, dotMetricsEnabled),
|
||||
[dotMetricsEnabled],
|
||||
);
|
||||
const controlListPrefix = !showFilters ? (
|
||||
<div className={styles.quickFiltersToggleContainer}>
|
||||
@@ -219,7 +226,7 @@ function Hosts(): JSX.Element {
|
||||
</div>
|
||||
<QuickFilters
|
||||
source={QuickFiltersSource.INFRA_MONITORING}
|
||||
config={getHostsQuickFiltersConfig()}
|
||||
config={getHostsQuickFiltersConfig(dotMetricsEnabled)}
|
||||
handleFilterVisibilityChange={handleFilterVisibilityChange}
|
||||
useFieldApis={{
|
||||
metricNamespace:
|
||||
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
InframonitoringtypesHostStatusDTO,
|
||||
} from 'api/generated/services/sigNoz.schemas';
|
||||
import { K8sDetailsMetadataConfig } from 'container/InfraMonitoringK8sV2/Base/K8sBaseDetails';
|
||||
import { INFRA_MONITORING_ATTR_KEYS } from 'container/InfraMonitoringK8sV2/constants';
|
||||
import { formatValueForExpression } from 'components/QueryBuilderV2/utils';
|
||||
import { INFRA_MONITORING_ATTR_KEYS } from 'container/InfraMonitoringK8sV2/constants';
|
||||
import { SelectedItemParams } from 'container/InfraMonitoringK8sV2/hooks';
|
||||
import {
|
||||
getHostQueryPayload,
|
||||
@@ -63,7 +63,7 @@ export const hostDetailsMetadataConfig: HostDetailMetadataConfigType[] = [
|
||||
},
|
||||
{
|
||||
label: 'OPERATING SYSTEM',
|
||||
getValue: (h): string => h.meta?.[INFRA_MONITORING_ATTR_KEYS.OS_TYPE] || '-',
|
||||
getValue: (h): string => h.meta?.['os.type'] || '-',
|
||||
render: (value): React.ReactNode =>
|
||||
value !== '-' ? (
|
||||
<Badge variant="outline" className={infraHostsStyles.infraMonitoringTags}>
|
||||
@@ -101,8 +101,9 @@ export function getHostMetricsQueryPayload(
|
||||
host: InframonitoringtypesHostRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
): ReturnType<typeof getHostQueryPayload> {
|
||||
return getHostQueryPayload(host.hostName, start, end, true);
|
||||
return getHostQueryPayload(host.hostName, start, end, dotMetricsEnabled);
|
||||
}
|
||||
|
||||
export { hostWidgetInfo };
|
||||
@@ -110,13 +111,17 @@ export { hostWidgetInfo };
|
||||
export const hostGetSelectedItemExpression = (
|
||||
params: SelectedItemParams,
|
||||
): string =>
|
||||
`${INFRA_MONITORING_ATTR_KEYS.HOST_NAME} = ${formatValueForExpression(params.selectedItem ?? '')}`;
|
||||
`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 `${INFRA_MONITORING_ATTR_KEYS.HOST_NAME} = ${hostName}`;
|
||||
return `${hostKey} = ${hostName}`;
|
||||
}
|
||||
|
||||
export function hostInitialEventsExpression(
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
IQuickFiltersConfig,
|
||||
} from 'components/QuickFilters/types';
|
||||
import { TriangleAlert } from '@signozhq/icons';
|
||||
import { CellValueTooltip } from 'container/InfraMonitoringK8sV2/components';
|
||||
import { INFRA_MONITORING_ATTR_KEYS } from 'container/InfraMonitoringK8sV2/constants';
|
||||
import { CellValueTooltip } from 'container/InfraMonitoringK8sV2/components';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
const HOSTNAME_DOCS_URL =
|
||||
@@ -62,18 +62,32 @@ export function HostnameCell({
|
||||
);
|
||||
}
|
||||
|
||||
export function getHostsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
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';
|
||||
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Host Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.HOST_NAME,
|
||||
key: hostNameKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.SYSTEM_CPU_LOAD_AVERAGE_15M,
|
||||
aggregateAttribute: metricName,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -81,12 +95,12 @@ export function getHostsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'OS Type',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.OS_TYPE,
|
||||
key: osTypeKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.SYSTEM_CPU_LOAD_AVERAGE_15M,
|
||||
aggregateAttribute: metricName,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -94,7 +108,7 @@ export function getHostsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
key: environmentKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
|
||||
@@ -70,6 +70,7 @@ export type GetEntityQueryPayload<T> = (
|
||||
entity: T,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
) => GetQueryResultsProps[];
|
||||
|
||||
export interface K8sDetailsTabsConfig {
|
||||
|
||||
@@ -9,14 +9,33 @@ 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((key) => {
|
||||
result[key] = meta[key] ?? '';
|
||||
groupBy.forEach((rawKey) => {
|
||||
const metaKey = (dotToUnder[rawKey] ?? rawKey) as keyof typeof meta;
|
||||
result[rawKey] = (meta[metaKey] || meta[rawKey]) ?? '';
|
||||
});
|
||||
|
||||
return result;
|
||||
@@ -28,8 +47,9 @@ export function getGroupByEl<
|
||||
const groupByValues: string[] = [];
|
||||
const meta = itemData.meta ?? {};
|
||||
|
||||
groupBy.forEach((key) => {
|
||||
const value = meta[key] || '<no-value>';
|
||||
groupBy.forEach((rawKey) => {
|
||||
const metaKey = (dotToUnder[rawKey] ?? rawKey) as keyof typeof meta;
|
||||
const value = meta[metaKey] || meta[rawKey] || '<no-value>';
|
||||
|
||||
groupByValues.push(value);
|
||||
});
|
||||
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
export const k8sClusterGetSelectedItemExpression = (
|
||||
params: SelectedItemParams,
|
||||
): string =>
|
||||
`${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME} = ${formatValueForExpression(params.selectedItem ?? '')}`;
|
||||
`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 =>
|
||||
`${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME} = ${formatValueForExpression(item.clusterName ?? '')}`;
|
||||
`k8s.cluster.name = ${formatValueForExpression(item.clusterName ?? '')}`;
|
||||
|
||||
export const clusterWidgetInfo = [
|
||||
{
|
||||
@@ -138,7 +138,96 @@ 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',
|
||||
@@ -150,7 +239,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_cpu_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -164,7 +253,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -189,7 +278,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_cpu_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'min',
|
||||
@@ -203,7 +292,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -228,7 +317,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_cpu_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -242,7 +331,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -267,7 +356,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_allocatable_cpu--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_ALLOCATABLE_CPU,
|
||||
key: k8sNodeAllocatableCpuKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -281,7 +370,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -340,7 +429,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_memory_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
key: k8sPodMemoryUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -354,7 +443,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -379,7 +468,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_memory_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
key: k8sPodMemoryUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'min',
|
||||
@@ -393,7 +482,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -418,7 +507,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_memory_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
key: k8sPodMemoryUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -432,7 +521,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -457,7 +546,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_allocatable_memory--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_ALLOCATABLE_MEMORY,
|
||||
key: k8sNodeAllocatableMemoryKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -471,7 +560,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -530,7 +619,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_condition_ready--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CONDITION_READY,
|
||||
key: k8sNodeConditionReadyKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -544,7 +633,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -558,18 +647,18 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
having: [
|
||||
{
|
||||
columnName: `MAX(${INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CONDITION_READY})`,
|
||||
columnName: `MAX(${k8sNodeConditionReadyKey})`,
|
||||
op: '=',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME}}}`,
|
||||
legend: `{{${k8sNodeNameKey}}}`,
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
@@ -616,7 +705,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_condition_ready--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CONDITION_READY,
|
||||
key: k8sNodeConditionReadyKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -630,7 +719,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -644,18 +733,18 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
having: [
|
||||
{
|
||||
columnName: `MAX(${INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CONDITION_READY})`,
|
||||
columnName: `MAX(${k8sNodeConditionReadyKey})`,
|
||||
op: '=',
|
||||
value: 0,
|
||||
},
|
||||
],
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME}}}`,
|
||||
legend: `{{${k8sNodeNameKey}}}`,
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
@@ -702,7 +791,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_deployment_available--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_AVAILABLE,
|
||||
key: k8sDeploymentAvailableKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -716,7 +805,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -730,13 +819,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_deployment_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
key: k8sDeploymentNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -754,7 +843,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_deployment_desired--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_DESIRED,
|
||||
key: k8sDeploymentDesiredKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -768,7 +857,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -782,13 +871,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_deployment_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
key: k8sDeploymentNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -852,7 +941,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_statefulset_current_pods--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_CURRENT_PODS,
|
||||
key: k8sStatefulsetCurrentPodsKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -866,7 +955,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -880,13 +969,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_statefulset_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: k8sStatefulsetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -904,7 +993,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_statefulset_desired_pods--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_DESIRED_PODS,
|
||||
key: k8sStatefulsetDesiredPodsKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -918,7 +1007,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -932,13 +1021,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_statefulset_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: k8sStatefulsetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -956,7 +1045,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_statefulset_ready_pods--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_READY_PODS,
|
||||
key: k8sStatefulsetReadyPodsKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -970,7 +1059,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -984,13 +1073,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_statefulset_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: k8sStatefulsetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1008,7 +1097,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_statefulset_updated_pods--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_UPDATED_PODS,
|
||||
key: k8sStatefulsetUpdatedPodsKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -1022,7 +1111,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1036,13 +1125,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_statefulset_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: k8sStatefulsetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1130,7 +1219,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_daemonset_current_scheduled_nodes--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_CURRENT_SCHEDULED_NODES,
|
||||
key: k8sDaemonsetCurrentScheduledNodesKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1144,7 +1233,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1158,7 +1247,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_daemonset_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
key: k8sDaemonsetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1176,7 +1265,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_daemonset_desired_scheduled_nodes--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_DESIRED_SCHEDULED_NODES,
|
||||
key: k8sDaemonsetDesiredScheduledNodesKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1190,7 +1279,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1204,7 +1293,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_daemonset_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
key: k8sDaemonsetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1222,7 +1311,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_daemonset_ready_nodes--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_READY_NODES,
|
||||
key: k8sDaemonsetReadyNodesKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1236,7 +1325,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1250,7 +1339,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_daemonset_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
key: k8sDaemonsetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1326,7 +1415,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_job_active_pods--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_ACTIVE_PODS,
|
||||
key: k8sJobActivePodsKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -1340,7 +1429,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1354,13 +1443,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_job_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME,
|
||||
key: k8sJobNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1378,7 +1467,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_job_successful_pods--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_SUCCESSFUL_PODS,
|
||||
key: k8sJobSuccessfulPodsKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -1392,7 +1481,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1406,13 +1495,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_job_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME,
|
||||
key: k8sJobNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1430,7 +1519,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_job_failed_pods--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_FAILED_PODS,
|
||||
key: k8sJobFailedPodsKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -1444,7 +1533,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1458,13 +1547,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_job_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME,
|
||||
key: k8sJobNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1482,7 +1571,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_job_desired_successful_pods--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_DESIRED_SUCCESSFUL_PODS,
|
||||
key: k8sJobDesiredSuccessfulPodsKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -1496,7 +1585,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1510,13 +1599,13 @@ export const getClusterMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_job_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME,
|
||||
key: k8sJobNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
|
||||
@@ -100,7 +100,54 @@ 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 =
|
||||
@@ -112,7 +159,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -123,7 +170,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -142,7 +189,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_cpu_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -156,7 +203,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_daemonset_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
key: k8sDaemonSetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -184,7 +231,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_cpu_request--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_REQUEST,
|
||||
key: k8sContainerCpuRequestKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -198,7 +245,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: k8sPodNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -226,7 +273,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_cpu_limit--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_LIMIT,
|
||||
key: k8sContainerCpuLimitKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -240,7 +287,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: k8sPodNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -302,7 +349,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_memory_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
key: k8sPodMemoryUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -316,7 +363,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_daemonset_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
key: k8sDaemonSetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -344,7 +391,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_memory_request--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_REQUEST,
|
||||
key: k8sContainerMemoryRequestKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -358,7 +405,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: k8sPodNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -386,7 +433,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_memory_limit--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_LIMIT,
|
||||
key: k8sContainerMemoryLimitKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -400,7 +447,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: k8sPodNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -462,7 +509,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_network_io--float64--Sum--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_IO,
|
||||
key: k8sPodNetworkIoKey,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'rate',
|
||||
@@ -476,7 +523,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_daemonset_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
key: k8sDaemonSetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -551,7 +598,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_network_errors--float64--Sum--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_ERRORS,
|
||||
key: k8sPodNetworkErrorsKey,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'increase',
|
||||
@@ -565,7 +612,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_daemonset_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
key: k8sDaemonSetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -637,10 +684,15 @@ export const getDaemonSetPodMetricsQueryPayload = (
|
||||
daemonSet: InframonitoringtypesDaemonSetRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
): GetQueryResultsProps[] => {
|
||||
const k8sDaemonSetNameKey = dotMetricsEnabled
|
||||
? 'k8s.daemonset.name'
|
||||
: 'k8s_daemonset_name';
|
||||
|
||||
return getPodUtilizationByPodQueryPayloads(
|
||||
{
|
||||
workloadNameKey: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
workloadNameKey: k8sDaemonSetNameKey,
|
||||
workloadNameValue:
|
||||
daemonSet.meta?.[INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME] ?? '',
|
||||
clusterName:
|
||||
@@ -650,5 +702,6 @@ export const getDaemonSetPodMetricsQueryPayload = (
|
||||
},
|
||||
start,
|
||||
end,
|
||||
dotMetricsEnabled,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -100,7 +100,52 @@ 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] ?? '';
|
||||
|
||||
@@ -113,7 +158,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -124,7 +169,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -143,7 +188,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_cpu_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -157,7 +202,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_deployment_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
key: k8sDeploymentNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -185,7 +230,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_cpu_request--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_REQUEST,
|
||||
key: k8sContainerCpuRequestKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -199,7 +244,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: k8sPodNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -227,7 +272,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_cpu_limit--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_LIMIT,
|
||||
key: k8sContainerCpuLimitKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -241,7 +286,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: k8sPodNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -303,7 +348,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_memory_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
key: k8sPodMemoryUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -317,7 +362,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_deployment_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
key: k8sDeploymentNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -345,7 +390,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_memory_request--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_REQUEST,
|
||||
key: k8sContainerMemoryRequestKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -359,7 +404,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: k8sPodNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -387,7 +432,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_memory_limit--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_LIMIT,
|
||||
key: k8sContainerMemoryLimitKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -401,7 +446,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: k8sPodNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -463,7 +508,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_network_io--float64--Sum--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_IO,
|
||||
key: k8sPodNetworkIoKey,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'rate',
|
||||
@@ -477,7 +522,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_deployment_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
key: k8sDeploymentNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -552,7 +597,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_network_errors--float64--Sum--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_ERRORS,
|
||||
key: k8sPodNetworkErrorsKey,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'increase',
|
||||
@@ -566,7 +611,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_deployment_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
key: k8sDeploymentNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -638,10 +683,15 @@ export const getDeploymentPodMetricsQueryPayload = (
|
||||
deployment: InframonitoringtypesDeploymentRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
): GetQueryResultsProps[] =>
|
||||
getPodUtilizationByPodQueryPayloads(
|
||||
dotMetricsEnabled: boolean,
|
||||
): GetQueryResultsProps[] => {
|
||||
const k8sDeploymentNameKey = dotMetricsEnabled
|
||||
? 'k8s.deployment.name'
|
||||
: 'k8s_deployment_name';
|
||||
|
||||
return getPodUtilizationByPodQueryPayloads(
|
||||
{
|
||||
workloadNameKey: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
workloadNameKey: k8sDeploymentNameKey,
|
||||
workloadNameValue:
|
||||
deployment.meta?.[INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME] ?? '',
|
||||
clusterName:
|
||||
@@ -651,4 +701,6 @@ export const getDeploymentPodMetricsQueryPayload = (
|
||||
},
|
||||
start,
|
||||
end,
|
||||
dotMetricsEnabled,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -40,6 +40,7 @@ interface EntityMetricsProps<T> {
|
||||
node: T,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
) => GetQueryResultsProps[];
|
||||
queryKey: string;
|
||||
category: InfraMonitoringEntity;
|
||||
|
||||
@@ -85,6 +85,7 @@ describe('EntityMetrics time range wiring', () => {
|
||||
entity,
|
||||
START_SECONDS,
|
||||
END_SECONDS,
|
||||
false,
|
||||
);
|
||||
expect(mockBuildChartConfig).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
|
||||
@@ -13,6 +13,8 @@ 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> {
|
||||
@@ -23,6 +25,7 @@ export interface UseEntityMetricsParams<T> {
|
||||
entity: T,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
) => GetQueryResultsProps[];
|
||||
visibilities: boolean[];
|
||||
category: InfraMonitoringEntity;
|
||||
@@ -43,9 +46,26 @@ 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),
|
||||
[getEntityQueryPayload, entity, timeRange.startTime, timeRange.endTime],
|
||||
() =>
|
||||
getEntityQueryPayload(
|
||||
entity,
|
||||
timeRange.startTime,
|
||||
timeRange.endTime,
|
||||
dotMetricsEnabled,
|
||||
),
|
||||
[
|
||||
getEntityQueryPayload,
|
||||
entity,
|
||||
timeRange.startTime,
|
||||
timeRange.endTime,
|
||||
dotMetricsEnabled,
|
||||
],
|
||||
);
|
||||
|
||||
const queries = useQueries(
|
||||
|
||||
@@ -30,6 +30,7 @@ interface CreatePodMetricsTabParams<T> {
|
||||
entity: T,
|
||||
start: number,
|
||||
end: number,
|
||||
dotMetricsEnabled: boolean,
|
||||
) => GetQueryResultsProps[];
|
||||
queryKey: string;
|
||||
category: InfraMonitoringEntity;
|
||||
|
||||
@@ -26,6 +26,8 @@ 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,
|
||||
@@ -126,64 +128,69 @@ 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(),
|
||||
config: GetPodsQuickFiltersConfig(dotMetricsEnabled),
|
||||
},
|
||||
{
|
||||
key: K8sCategories.NODES,
|
||||
label: 'Nodes',
|
||||
icon: <Workflow size={14} />,
|
||||
config: GetNodesQuickFiltersConfig(),
|
||||
config: GetNodesQuickFiltersConfig(dotMetricsEnabled),
|
||||
},
|
||||
{
|
||||
key: K8sCategories.NAMESPACES,
|
||||
label: 'Namespaces',
|
||||
icon: <FilePenLine size={14} />,
|
||||
config: GetNamespaceQuickFiltersConfig(),
|
||||
config: GetNamespaceQuickFiltersConfig(dotMetricsEnabled),
|
||||
},
|
||||
{
|
||||
key: K8sCategories.CLUSTERS,
|
||||
label: 'Clusters',
|
||||
icon: <Boxes size={14} />,
|
||||
config: GetClustersQuickFiltersConfig(),
|
||||
config: GetClustersQuickFiltersConfig(dotMetricsEnabled),
|
||||
},
|
||||
{
|
||||
key: K8sCategories.DEPLOYMENTS,
|
||||
label: 'Deployments',
|
||||
icon: <Computer size={14} />,
|
||||
config: GetDeploymentsQuickFiltersConfig(),
|
||||
config: GetDeploymentsQuickFiltersConfig(dotMetricsEnabled),
|
||||
},
|
||||
{
|
||||
key: K8sCategories.JOBS,
|
||||
label: 'Jobs',
|
||||
icon: <Bolt size={14} />,
|
||||
config: GetJobsQuickFiltersConfig(),
|
||||
config: GetJobsQuickFiltersConfig(dotMetricsEnabled),
|
||||
},
|
||||
{
|
||||
key: K8sCategories.DAEMONSETS,
|
||||
label: 'DaemonSets',
|
||||
icon: <Group size={14} />,
|
||||
config: GetDaemonsetsQuickFiltersConfig(),
|
||||
config: GetDaemonsetsQuickFiltersConfig(dotMetricsEnabled),
|
||||
},
|
||||
{
|
||||
key: K8sCategories.STATEFULSETS,
|
||||
label: 'StatefulSets',
|
||||
icon: <ArrowUpDown size={14} />,
|
||||
config: GetStatefulsetsQuickFiltersConfig(),
|
||||
config: GetStatefulsetsQuickFiltersConfig(dotMetricsEnabled),
|
||||
},
|
||||
{
|
||||
key: K8sCategories.VOLUMES,
|
||||
label: 'Volumes',
|
||||
icon: <HardDrive size={14} />,
|
||||
config: GetVolumesQuickFiltersConfig(),
|
||||
config: GetVolumesQuickFiltersConfig(dotMetricsEnabled),
|
||||
},
|
||||
],
|
||||
[],
|
||||
[dotMetricsEnabled],
|
||||
);
|
||||
|
||||
const selectedCategoryConfig = useMemo(
|
||||
|
||||
@@ -96,7 +96,28 @@ 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 =
|
||||
@@ -108,7 +129,7 @@ export const getJobMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_job_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME,
|
||||
key: k8sJobNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -119,7 +140,7 @@ export const getJobMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -130,7 +151,7 @@ export const getJobMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -149,7 +170,7 @@ export const getJobMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_cpu_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -210,7 +231,7 @@ export const getJobMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_memory_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
key: k8sPodMemoryUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -271,7 +292,7 @@ export const getJobMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_network_io--float64--Sum--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_IO,
|
||||
key: k8sPodNetworkIoKey,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'rate',
|
||||
@@ -345,7 +366,7 @@ export const getJobMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_network_errors--float64--Sum--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_ERRORS,
|
||||
key: k8sPodNetworkErrorsKey,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'increase',
|
||||
@@ -416,10 +437,13 @@ export const getJobPodMetricsQueryPayload = (
|
||||
job: InframonitoringtypesJobRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
): GetQueryResultsProps[] =>
|
||||
getPodUtilizationByPodQueryPayloads(
|
||||
dotMetricsEnabled: boolean,
|
||||
): GetQueryResultsProps[] => {
|
||||
const k8sJobNameKey = dotMetricsEnabled ? 'k8s.job.name' : 'k8s_job_name';
|
||||
|
||||
return getPodUtilizationByPodQueryPayloads(
|
||||
{
|
||||
workloadNameKey: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME,
|
||||
workloadNameKey: k8sJobNameKey,
|
||||
workloadNameValue: job.jobName ?? '',
|
||||
clusterName: job.meta?.[INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME] ?? '',
|
||||
namespaceName:
|
||||
@@ -427,4 +451,6 @@ export const getJobPodMetricsQueryPayload = (
|
||||
},
|
||||
start,
|
||||
end,
|
||||
dotMetricsEnabled,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -166,7 +166,97 @@ 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] ?? '';
|
||||
|
||||
@@ -176,7 +266,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -194,8 +284,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
id: k8sPodCpuUtilizationKey,
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -208,8 +298,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '47b3adae',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -234,8 +324,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_REQUEST,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_REQUEST,
|
||||
id: k8sContainerCpuRequestKey,
|
||||
key: k8sContainerCpuRequestKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -248,8 +338,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '93d2be5e',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -274,8 +364,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
id: k8sPodCpuUtilizationKey,
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'min',
|
||||
@@ -288,8 +378,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '795eb679',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -314,8 +404,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
id: k8sPodCpuUtilizationKey,
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -328,8 +418,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '6792adbe',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -388,8 +478,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
id: k8sPodMemoryUsageKey,
|
||||
key: k8sPodMemoryUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -402,8 +492,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '10011298',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -428,8 +518,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_REQUEST,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_REQUEST,
|
||||
id: k8sContainerMemoryRequestKey,
|
||||
key: k8sContainerMemoryRequestKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -442,8 +532,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: 'ea53b656',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -468,8 +558,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_WORKING_SET,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_WORKING_SET,
|
||||
id: k8sPodMemoryWorkingSetKey,
|
||||
key: k8sPodMemoryWorkingSetKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -482,8 +572,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '674ace83',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -508,8 +598,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_RSS,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_RSS,
|
||||
id: k8sPodMemoryRssKey,
|
||||
key: k8sPodMemoryRssKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -522,8 +612,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '187dbdb3',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -548,8 +638,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
id: k8sPodMemoryUsageKey,
|
||||
key: k8sPodMemoryUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'min',
|
||||
@@ -562,8 +652,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: 'a3dbf468',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -588,8 +678,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
id: k8sPodMemoryUsageKey,
|
||||
key: k8sPodMemoryUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -602,8 +692,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '4b2406c2',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -662,8 +752,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
id: k8sPodCpuUtilizationKey,
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -676,8 +766,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: 'c3a73f0a',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -691,13 +781,13 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
id: k8sPodNameKey,
|
||||
key: k8sPodNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
having: [],
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}}}`,
|
||||
legend: `{{${k8sPodNameKey}}}`,
|
||||
limit: 10,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
@@ -743,8 +833,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
id: k8sPodMemoryUsageKey,
|
||||
key: k8sPodMemoryUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -757,8 +847,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '5cad3379',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -772,13 +862,13 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
id: k8sPodNameKey,
|
||||
key: k8sPodNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
having: [],
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}}}`,
|
||||
legend: `{{${k8sPodNameKey}}}`,
|
||||
limit: 10,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
@@ -824,8 +914,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_IO,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_IO,
|
||||
id: k8sPodNetworkIoKey,
|
||||
key: k8sPodNetworkIoKey,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'rate',
|
||||
@@ -838,8 +928,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '00f5c5e1',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -911,8 +1001,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_ERRORS,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_ERRORS,
|
||||
id: k8sPodNetworkErrorsKey,
|
||||
key: k8sPodNetworkErrorsKey,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'increase',
|
||||
@@ -925,8 +1015,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '3aa8e064',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -998,8 +1088,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_CURRENT_PODS,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_CURRENT_PODS,
|
||||
id: k8sStatefulsetCurrentPodsKey,
|
||||
key: k8sStatefulsetCurrentPodsKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1012,8 +1102,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '5f2a55c5',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1027,8 +1117,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
id: k8sStatefulsetNameKey,
|
||||
key: k8sStatefulsetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1045,8 +1135,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_DESIRED_PODS,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_DESIRED_PODS,
|
||||
id: k8sStatefulsetDesiredPodsKey,
|
||||
key: k8sStatefulsetDesiredPodsKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1059,8 +1149,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '13bd7a1d',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1074,8 +1164,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
id: k8sStatefulsetNameKey,
|
||||
key: k8sStatefulsetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1092,8 +1182,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_UPDATED_PODS,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_UPDATED_PODS,
|
||||
id: k8sStatefulsetUpdatedPodsKey,
|
||||
key: k8sStatefulsetUpdatedPodsKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1106,8 +1196,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '9d287c73',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1121,8 +1211,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
id: k8sStatefulsetNameKey,
|
||||
key: k8sStatefulsetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1173,8 +1263,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_DESIRED,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_DESIRED,
|
||||
id: k8sReplicasetDesiredKey,
|
||||
key: k8sReplicasetDesiredKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1187,8 +1277,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '0c1e655c',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1202,14 +1292,14 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_NAME,
|
||||
id: k8sReplicasetNameKey,
|
||||
key: k8sReplicasetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
having: [
|
||||
{
|
||||
columnName: `MAX(${INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_DESIRED})`,
|
||||
columnName: `MAX(${k8sReplicasetDesiredKey})`,
|
||||
op: '>',
|
||||
value: 0,
|
||||
},
|
||||
@@ -1226,8 +1316,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_AVAILABLE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_AVAILABLE,
|
||||
id: k8sReplicasetAvailableKey,
|
||||
key: k8sReplicasetAvailableKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1240,8 +1330,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: 'b2296bdb',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1255,14 +1345,14 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_NAME,
|
||||
id: k8sReplicasetNameKey,
|
||||
key: k8sReplicasetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
having: [
|
||||
{
|
||||
columnName: `MAX(${INFRA_MONITORING_ATTR_KEYS.K8S_REPLICASET_DESIRED})`,
|
||||
columnName: `MAX(${k8sReplicasetDesiredKey})`,
|
||||
op: '>',
|
||||
value: 0,
|
||||
},
|
||||
@@ -1313,8 +1403,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_DESIRED_SCHEDULED_NODES,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_DESIRED_SCHEDULED_NODES,
|
||||
id: k8sDaemonsetDesiredScheduledNodesKey,
|
||||
key: k8sDaemonsetDesiredScheduledNodesKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1327,8 +1417,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '2964eb92',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1342,8 +1432,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
id: k8sDaemonsetNameKey,
|
||||
key: k8sDaemonsetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1360,8 +1450,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_CURRENT_SCHEDULED_NODES,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_CURRENT_SCHEDULED_NODES,
|
||||
id: k8sDaemonsetCurrentScheduledNodesKey,
|
||||
key: k8sDaemonsetCurrentScheduledNodesKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1374,8 +1464,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: 'cd324eff',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1389,8 +1479,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
id: k8sDaemonsetNameKey,
|
||||
key: k8sDaemonsetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1407,8 +1497,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_READY_NODES,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_READY_NODES,
|
||||
id: k8sDaemonsetReadyNodesKey,
|
||||
key: k8sDaemonsetReadyNodesKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1421,8 +1511,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '0416fa6f',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1436,8 +1526,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
id: k8sDaemonsetNameKey,
|
||||
key: k8sDaemonsetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1454,8 +1544,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_MISSCHEDULED_NODES,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_MISSCHEDULED_NODES,
|
||||
id: k8sDaemonsetMisscheduledNodesKey,
|
||||
key: k8sDaemonsetMisscheduledNodesKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1468,8 +1558,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: 'c0a126d3',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1483,8 +1573,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
id: k8sDaemonsetNameKey,
|
||||
key: k8sDaemonsetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1535,8 +1625,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_DESIRED,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_DESIRED,
|
||||
id: k8sDeploymentDesiredKey,
|
||||
key: k8sDeploymentDesiredKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -1549,8 +1639,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: '9bc659c1',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1564,8 +1654,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
id: k8sDeploymentNameKey,
|
||||
key: k8sDeploymentNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1582,8 +1672,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
{
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_AVAILABLE,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_AVAILABLE,
|
||||
id: k8sDeploymentAvailableKey,
|
||||
key: k8sDeploymentAvailableKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1596,8 +1686,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
id: 'e1696631',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: k8sNamespaceNameKey,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1611,8 +1701,8 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
groupBy: [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
id: k8sDeploymentNameKey,
|
||||
key: k8sDeploymentNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
@@ -1668,14 +1758,21 @@ export const getNamespacePodMetricsQueryPayload = (
|
||||
namespace: InframonitoringtypesNamespaceRecordDTO,
|
||||
start: number,
|
||||
end: number,
|
||||
): GetQueryResultsProps[] =>
|
||||
getPodUtilizationByPodQueryPayloads(
|
||||
dotMetricsEnabled: boolean,
|
||||
): GetQueryResultsProps[] => {
|
||||
const k8sNamespaceNameKey = dotMetricsEnabled
|
||||
? 'k8s.namespace.name'
|
||||
: 'k8s_namespace_name';
|
||||
|
||||
return getPodUtilizationByPodQueryPayloads(
|
||||
{
|
||||
workloadNameKey: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
workloadNameKey: k8sNamespaceNameKey,
|
||||
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 =>
|
||||
`${INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME} = ${formatValueForExpression(params.selectedItem ?? '')}`;
|
||||
`k8s.node.name = ${formatValueForExpression(params.selectedItem ?? '')}`;
|
||||
|
||||
export const k8sNodeDetailsMetadataConfig: K8sDetailsMetadataConfig<InframonitoringtypesNodeRecordDTO>[] =
|
||||
[
|
||||
@@ -111,7 +111,89 @@ 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',
|
||||
@@ -123,7 +205,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_cpu_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CPU_USAGE,
|
||||
key: k8sNodeCpuUtilizationKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -137,7 +219,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -162,7 +244,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_allocatable_cpu--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_ALLOCATABLE_CPU,
|
||||
key: k8sNodeAllocatableCpuKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -176,7 +258,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -201,7 +283,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_cpu_request--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_REQUEST,
|
||||
key: k8sContainerCpuRequestKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -215,7 +297,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -240,7 +322,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_cpu_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CPU_USAGE,
|
||||
key: k8sNodeCpuUtilizationKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -254,7 +336,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -279,7 +361,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_cpu_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CPU_USAGE,
|
||||
key: k8sNodeCpuUtilizationKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'min',
|
||||
@@ -293,7 +375,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -352,7 +434,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_memory_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_MEMORY_USAGE,
|
||||
key: k8sNodeMemoryUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -366,7 +448,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -391,7 +473,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_allocatable_memory--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_ALLOCATABLE_MEMORY,
|
||||
key: k8sNodeAllocatableMemoryKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -405,7 +487,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -430,7 +512,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_memory_request--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_REQUEST,
|
||||
key: k8sContainerMemoryRequestKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -444,7 +526,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -469,7 +551,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_memory_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_MEMORY_USAGE,
|
||||
key: k8sNodeMemoryUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'max',
|
||||
@@ -483,7 +565,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -508,7 +590,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_memory_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_MEMORY_USAGE,
|
||||
key: k8sNodeMemoryUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'min',
|
||||
@@ -522,7 +604,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -547,7 +629,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_memory_working_set--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_MEMORY_WORKING_SET,
|
||||
key: k8sNodeMemoryWorkingSetKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -561,7 +643,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -586,7 +668,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_memory_rss--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_MEMORY_RSS,
|
||||
key: k8sNodeMemoryRssKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -600,7 +682,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -659,7 +741,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_cpu_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CPU_USAGE,
|
||||
key: k8sNodeCpuUtilizationKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -673,7 +755,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -698,7 +780,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_allocatable_cpu--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_ALLOCATABLE_CPU,
|
||||
key: k8sNodeAllocatableCpuKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -712,7 +794,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -737,7 +819,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_cpu_request--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_REQUEST,
|
||||
key: k8sContainerCpuRequestKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -751,7 +833,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -823,7 +905,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_memory_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_MEMORY_USAGE,
|
||||
key: k8sNodeMemoryUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -837,7 +919,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -862,7 +944,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_allocatable_memory--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_ALLOCATABLE_MEMORY,
|
||||
key: k8sNodeAllocatableMemoryKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -876,7 +958,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -901,7 +983,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_container_memory_request--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_REQUEST,
|
||||
key: k8sContainerMemoryRequestKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -915,7 +997,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -987,7 +1069,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_cpu_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
key: k8sPodCpuUtilizationKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1001,7 +1083,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1015,12 +1097,12 @@ export const getNodeMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: k8sPodNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
having: [],
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}}}`,
|
||||
legend: `{{${k8sPodNameKey}}}`,
|
||||
limit: 10,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
@@ -1067,7 +1149,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_pod_memory_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
key: k8sPodMemoryUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1081,7 +1163,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1095,12 +1177,12 @@ export const getNodeMetricsQueryPayload = (
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_pod_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: k8sPodNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
having: [],
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}}}`,
|
||||
legend: `{{${k8sPodNameKey}}}`,
|
||||
limit: 10,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
@@ -1147,7 +1229,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_network_errors--float64--Sum--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NETWORK_ERRORS,
|
||||
key: k8sNodeNetworkErrorsKey,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'increase',
|
||||
@@ -1161,7 +1243,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1233,7 +1315,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_network_io--float64--Sum--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NETWORK_IO,
|
||||
key: k8sNodeNetworkIoKey,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'rate',
|
||||
@@ -1247,7 +1329,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1319,7 +1401,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_filesystem_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_FILESYSTEM_USAGE,
|
||||
key: k8sNodeFilesystemUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1333,7 +1415,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1358,7 +1440,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_filesystem_capacity--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_FILESYSTEM_CAPACITY,
|
||||
key: k8sNodeFilesystemCapacityKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1372,7 +1454,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1397,7 +1479,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_filesystem_available--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_FILESYSTEM_AVAILABLE,
|
||||
key: k8sNodeFilesystemAvailableKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1411,7 +1493,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1470,7 +1552,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_filesystem_usage--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_FILESYSTEM_USAGE,
|
||||
key: k8sNodeFilesystemUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1484,7 +1566,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -1509,7 +1591,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_node_filesystem_capacity--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_FILESYSTEM_CAPACITY,
|
||||
key: k8sNodeFilesystemCapacityKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -1523,7 +1605,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_node_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: k8sNodeNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -113,7 +113,21 @@ 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 =
|
||||
@@ -125,7 +139,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -136,7 +150,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -144,6 +158,45 @@ 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',
|
||||
@@ -155,7 +208,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'cpu_usage',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
key: k8sPodCpuUtilKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -169,7 +222,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'ss_name',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: k8sStatefulSetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -198,7 +251,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'cpu_request',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_REQUEST,
|
||||
key: k8sContainerCpuRequestKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -212,7 +265,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'pod_name',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: k8sPodNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -241,7 +294,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'cpu_limit',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_CPU_LIMIT,
|
||||
key: k8sContainerCpuLimitKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -255,7 +308,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'pod_name',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: k8sPodNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -304,7 +357,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'cpu_req_util',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_REQUEST_UTILIZATION,
|
||||
key: k8sPodCpuReqUtilKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -318,7 +371,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'ss_name',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: k8sStatefulSetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -347,7 +400,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'cpu_limit_util',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_LIMIT_UTILIZATION,
|
||||
key: k8sPodCpuLimitUtilKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -361,7 +414,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'ss_name',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: k8sStatefulSetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -410,7 +463,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'mem_usage',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_USAGE,
|
||||
key: k8sPodMemUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -424,7 +477,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'ss_name',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: k8sStatefulSetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -453,7 +506,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'mem_request',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_REQUEST,
|
||||
key: k8sContainerMemRequestKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -467,7 +520,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'pod_name',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: k8sPodNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -496,7 +549,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'mem_limit',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CONTAINER_MEMORY_LIMIT,
|
||||
key: k8sContainerMemLimitKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'latest',
|
||||
@@ -510,7 +563,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'pod_name',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: k8sPodNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'contains',
|
||||
@@ -559,7 +612,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'mem_req_util',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_REQUEST_UTILIZATION,
|
||||
key: k8sPodMemReqUtilKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -573,7 +626,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'ss_name',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: k8sStatefulSetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -602,7 +655,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'mem_limit_util',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_MEMORY_LIMIT_UTILIZATION,
|
||||
key: k8sPodMemLimitUtilKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -616,7 +669,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'ss_name',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: k8sStatefulSetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -665,7 +718,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'net_io',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_IO,
|
||||
key: k8sPodNetworkIoKey,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'rate',
|
||||
@@ -679,7 +732,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'ss_name',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: k8sStatefulSetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -741,7 +794,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'net_err',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NETWORK_ERRORS,
|
||||
key: k8sPodNetworkErrorsKey,
|
||||
type: 'Sum',
|
||||
},
|
||||
aggregateOperator: 'increase',
|
||||
@@ -755,7 +808,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'ss_name',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: k8sStatefulSetNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -814,10 +867,15 @@ 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: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
workloadNameKey: k8sStatefulSetNameKey,
|
||||
workloadNameValue:
|
||||
statefulSet.meta?.[INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME] ?? '',
|
||||
clusterName:
|
||||
@@ -827,5 +885,6 @@ export const getStatefulSetPodMetricsQueryPayload = (
|
||||
},
|
||||
start,
|
||||
end,
|
||||
dotMetricsEnabled,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -97,7 +97,36 @@ 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',
|
||||
@@ -109,7 +138,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_volume_available--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_AVAILABLE,
|
||||
key: k8sVolumeAvailableKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -123,7 +152,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -135,7 +164,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -148,7 +177,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_volume_type--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_TYPE,
|
||||
key: k8sVolumeTypeKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -159,7 +188,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_persistentvolumeclaim_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_PERSISTENT_VOLUME_CLAIM_NAME,
|
||||
key: k8sPVCNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -204,7 +233,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_volume_capacity--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_CAPACITY,
|
||||
key: k8sVolumeCapacityKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -218,7 +247,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -230,7 +259,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -243,7 +272,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_volume_type--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_TYPE,
|
||||
key: k8sVolumeTypeKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -254,7 +283,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_persistentvolumeclaim_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_PERSISTENT_VOLUME_CLAIM_NAME,
|
||||
key: k8sPVCNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -299,7 +328,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_volume_inodes_used--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_INODES_USED,
|
||||
key: k8sVolumeInodesUsedKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -313,7 +342,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -325,7 +354,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -338,7 +367,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_volume_type--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_TYPE,
|
||||
key: k8sVolumeTypeKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -349,7 +378,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_persistentvolumeclaim_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_PERSISTENT_VOLUME_CLAIM_NAME,
|
||||
key: k8sPVCNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -394,7 +423,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_volume_inodes--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_INODES,
|
||||
key: k8sVolumeInodesKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -408,7 +437,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -420,7 +449,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -433,7 +462,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_volume_type--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_TYPE,
|
||||
key: k8sVolumeTypeKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -444,7 +473,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_persistentvolumeclaim_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_PERSISTENT_VOLUME_CLAIM_NAME,
|
||||
key: k8sPVCNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -489,7 +518,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'k8s_volume_inodes_free--float64--Gauge--true',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_INODES_FREE,
|
||||
key: k8sVolumeInodesFreeKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -503,7 +532,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_cluster_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -515,7 +544,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_namespace_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -528,7 +557,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_volume_type--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_TYPE,
|
||||
key: k8sVolumeTypeKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: 'in',
|
||||
@@ -539,7 +568,7 @@ export const getVolumeMetricsQueryPayload = (
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: 'k8s_persistentvolumeclaim_name--string--tag--false',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_PERSISTENT_VOLUME_CLAIM_NAME,
|
||||
key: k8sPVCNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
|
||||
@@ -61,10 +61,6 @@ 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',
|
||||
@@ -113,10 +109,6 @@ 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;
|
||||
@@ -167,48 +159,81 @@ 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]:
|
||||
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,
|
||||
[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',
|
||||
};
|
||||
|
||||
export function GetK8sEntityToAggregateAttribute(
|
||||
category: InfraMonitoringEntity,
|
||||
dotMetricsEnabled: boolean,
|
||||
): string {
|
||||
return dotMap[category];
|
||||
return dotMetricsEnabled ? dotMap[category] : underscoreMap[category];
|
||||
}
|
||||
|
||||
export function GetPodsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
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';
|
||||
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Pod',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
key: podKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'tag',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}--string--tag--true`,
|
||||
id: `${podKey}--string--tag--true`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: cpuUtilizationMetric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -216,13 +241,13 @@ export function GetPodsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Namespace',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: namespaceKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME}--string--resource--false`,
|
||||
id: `${namespaceKey}--string--resource--false`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: cpuUtilizationMetric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: false,
|
||||
},
|
||||
@@ -230,13 +255,13 @@ export function GetPodsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Node',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: nodeKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME}--string--resource--false`,
|
||||
id: `${nodeKey}--string--resource--false`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: cpuUtilizationMetric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: false,
|
||||
},
|
||||
@@ -244,13 +269,13 @@ export function GetPodsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Cluster',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: clusterKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME}--string--resource--false`,
|
||||
id: `${clusterKey}--string--resource--false`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: cpuUtilizationMetric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: false,
|
||||
},
|
||||
@@ -258,13 +283,13 @@ export function GetPodsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Deployment',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
key: deploymentKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME}--string--resource--false`,
|
||||
id: `${deploymentKey}--string--resource--false`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: cpuUtilizationMetric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: false,
|
||||
},
|
||||
@@ -272,13 +297,13 @@ export function GetPodsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Statefulset',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: statefulsetKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME}--string--resource--false`,
|
||||
id: `${statefulsetKey}--string--resource--false`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: cpuUtilizationMetric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: false,
|
||||
},
|
||||
@@ -286,13 +311,13 @@ export function GetPodsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'DaemonSet',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
key: daemonsetKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME}--string--resource--false`,
|
||||
id: `${daemonsetKey}--string--resource--false`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: cpuUtilizationMetric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: false,
|
||||
},
|
||||
@@ -300,13 +325,13 @@ export function GetPodsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Job',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME,
|
||||
key: jobKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME}--string--resource--false`,
|
||||
id: `${jobKey}--string--resource--false`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: cpuUtilizationMetric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: false,
|
||||
},
|
||||
@@ -314,7 +339,7 @@ export function GetPodsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
key: environmentKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
@@ -323,19 +348,33 @@ export function GetPodsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
];
|
||||
}
|
||||
|
||||
export function GetNodesQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
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';
|
||||
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Node Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME,
|
||||
key: nodeKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_NODE_NAME}--string--resource--true`,
|
||||
id: `${nodeKey}--string--resource--true`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CPU_USAGE,
|
||||
aggregateAttribute: cpuUtilMetric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -343,13 +382,13 @@ export function GetNodesQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Cluster Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: clusterKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME}--string--resource--true`,
|
||||
id: `${clusterKey}--string--resource--true`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CPU_USAGE,
|
||||
aggregateAttribute: cpuUtilMetric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -357,7 +396,7 @@ export function GetNodesQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
key: environmentKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
@@ -366,19 +405,32 @@ export function GetNodesQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
];
|
||||
}
|
||||
|
||||
export function GetNamespaceQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
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';
|
||||
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Namespace Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: namespaceKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME}--string--resource`,
|
||||
id: `${namespaceKey}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: cpuUtilMetric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -386,13 +438,13 @@ export function GetNamespaceQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Cluster Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: clusterKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME}--string--resource`,
|
||||
id: `${clusterKey}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: cpuUtilMetric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -400,7 +452,7 @@ export function GetNamespaceQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
key: environmentKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
@@ -409,19 +461,29 @@ export function GetNamespaceQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
];
|
||||
}
|
||||
|
||||
export function GetClustersQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
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';
|
||||
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Cluster Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: clusterKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME}--string--resource`,
|
||||
id: `${clusterKey}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_NODE_CPU_USAGE,
|
||||
aggregateAttribute: cpuUtilMetric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -429,7 +491,7 @@ export function GetClustersQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
key: environmentKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
@@ -438,19 +500,35 @@ export function GetClustersQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
];
|
||||
}
|
||||
|
||||
export function GetVolumesQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
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';
|
||||
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'PVC Volume Claim Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_PERSISTENT_VOLUME_CLAIM_NAME,
|
||||
key: pvcKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_PERSISTENT_VOLUME_CLAIM_NAME}--string--resource`,
|
||||
id: `${pvcKey}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_CAPACITY,
|
||||
aggregateAttribute: volumeMetric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -458,13 +536,13 @@ export function GetVolumesQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Namespace Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: namespaceKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME}--string--resource`,
|
||||
id: `${namespaceKey}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_CAPACITY,
|
||||
aggregateAttribute: volumeMetric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -472,13 +550,13 @@ export function GetVolumesQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Cluster Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: clusterKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME}--string--resource`,
|
||||
id: `${clusterKey}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_VOLUME_CAPACITY,
|
||||
aggregateAttribute: volumeMetric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -486,7 +564,7 @@ export function GetVolumesQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
key: environmentKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
@@ -495,19 +573,33 @@ export function GetVolumesQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
];
|
||||
}
|
||||
|
||||
export function GetDeploymentsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
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';
|
||||
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Deployment Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME,
|
||||
key: deployKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_DEPLOYMENT_NAME}--string--resource`,
|
||||
id: `${deployKey}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: metric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -515,13 +607,13 @@ export function GetDeploymentsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Namespace Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: namespaceKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME}--string--resource`,
|
||||
id: `${namespaceKey}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: metric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -529,13 +621,13 @@ export function GetDeploymentsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Cluster Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: clusterKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME}--string--resource`,
|
||||
id: `${clusterKey}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: metric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -543,7 +635,7 @@ export function GetDeploymentsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
key: environmentKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
@@ -552,19 +644,33 @@ export function GetDeploymentsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
];
|
||||
}
|
||||
|
||||
export function GetStatefulsetsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
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';
|
||||
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Statefulset Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME,
|
||||
key: ssKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_STATEFULSET_NAME}--string--resource`,
|
||||
id: `${ssKey}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: metric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -572,13 +678,13 @@ export function GetStatefulsetsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Namespace Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: namespaceKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME}--string--resource`,
|
||||
id: `${namespaceKey}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: metric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -586,13 +692,13 @@ export function GetStatefulsetsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Cluster Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: clusterKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME}--string--resource`,
|
||||
id: `${clusterKey}--string--resource`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: metric,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -600,7 +706,7 @@ export function GetStatefulsetsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
key: environmentKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
@@ -609,19 +715,35 @@ export function GetStatefulsetsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
];
|
||||
}
|
||||
|
||||
export function GetDaemonsetsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
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';
|
||||
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'DaemonSet Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME,
|
||||
key: nameKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_DAEMONSET_NAME}--string--resource--true`,
|
||||
id: `${nameKey}--string--resource--true`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: metricName,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -629,12 +751,12 @@ export function GetDaemonsetsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Namespace Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: namespaceKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: metricName,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -642,12 +764,12 @@ export function GetDaemonsetsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Cluster Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: clusterKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: metricName,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -655,7 +777,7 @@ export function GetDaemonsetsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
key: environmentKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
@@ -664,19 +786,33 @@ export function GetDaemonsetsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
];
|
||||
}
|
||||
|
||||
export function GetJobsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
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';
|
||||
|
||||
return [
|
||||
{
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Job Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME,
|
||||
key: nameKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_JOB_NAME}--string--resource--true`,
|
||||
id: `${nameKey}--string--resource--true`,
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: metricName,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -684,12 +820,12 @@ export function GetJobsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Namespace Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
key: namespaceKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: metricName,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -697,12 +833,12 @@ export function GetJobsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Cluster Name',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
key: clusterKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: INFRA_MONITORING_ATTR_KEYS.K8S_POD_CPU_USAGE,
|
||||
aggregateAttribute: metricName,
|
||||
dataSource: DataSource.METRICS,
|
||||
defaultOpen: true,
|
||||
},
|
||||
@@ -710,7 +846,7 @@ export function GetJobsQuickFiltersConfig(): IQuickFiltersConfig[] {
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: INFRA_MONITORING_ATTR_KEYS.DEPLOYMENT_ENVIRONMENT,
|
||||
key: environmentKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
@@ -829,7 +965,39 @@ 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',
|
||||
@@ -846,8 +1014,8 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
id: 'cluster',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME}--string--tag--false`,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_CLUSTER_NAME,
|
||||
id: `${k8sClusterNameKey}--string--tag--false`,
|
||||
key: k8sClusterNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -859,8 +1027,8 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
id: 'namespace',
|
||||
key: {
|
||||
dataType: DataTypes.String,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME}--string--tag--false`,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_NAMESPACE_NAME,
|
||||
id: `${k8sNamespaceNameKey}--string--tag--false`,
|
||||
key: k8sNamespaceNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
op: '=',
|
||||
@@ -873,8 +1041,8 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
const podNameGroupBy = [
|
||||
{
|
||||
dataType: DataTypes.String,
|
||||
id: `${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}--string--tag--false`,
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME,
|
||||
id: `${k8sPodNameKey}--string--tag--false`,
|
||||
key: k8sPodNameKey,
|
||||
type: 'tag',
|
||||
},
|
||||
];
|
||||
@@ -906,7 +1074,7 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
functions: [],
|
||||
groupBy: podNameGroupBy,
|
||||
having: [],
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}}}`,
|
||||
legend: `{{${k8sPodNameKey}}}`,
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
@@ -940,7 +1108,7 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'fs_usage',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_FILESYSTEM_USAGE,
|
||||
key: k8sPodFsUsageKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -954,7 +1122,7 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
functions: [],
|
||||
groupBy: podNameGroupBy,
|
||||
having: [],
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}}}`,
|
||||
legend: `{{${k8sPodNameKey}}}`,
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
@@ -967,7 +1135,7 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
aggregateAttribute: {
|
||||
dataType: DataTypes.Float64,
|
||||
id: 'fs_capacity',
|
||||
key: INFRA_MONITORING_ATTR_KEYS.K8S_POD_FILESYSTEM_CAPACITY,
|
||||
key: k8sPodFsCapacityKey,
|
||||
type: 'Gauge',
|
||||
},
|
||||
aggregateOperator: 'avg',
|
||||
@@ -981,7 +1149,7 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
functions: [],
|
||||
groupBy: podNameGroupBy,
|
||||
having: [],
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}}}`,
|
||||
legend: `{{${k8sPodNameKey}}}`,
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
@@ -995,7 +1163,7 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
{
|
||||
disabled: false,
|
||||
expression: 'A/B',
|
||||
legend: `{{${INFRA_MONITORING_ATTR_KEYS.K8S_POD_NAME}}}`,
|
||||
legend: `{{${k8sPodNameKey}}}`,
|
||||
queryName: 'F1',
|
||||
},
|
||||
],
|
||||
@@ -1013,22 +1181,10 @@ export function getPodUtilizationByPodQueryPayloads(
|
||||
};
|
||||
|
||||
return [
|
||||
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',
|
||||
),
|
||||
buildSingleMetricQuery(k8sPodCpuLimitUtilKey, 'cpu_limit_util'),
|
||||
buildSingleMetricQuery(k8sPodCpuRequestUtilKey, 'cpu_request_util'),
|
||||
buildSingleMetricQuery(k8sPodMemLimitUtilKey, 'mem_limit_util'),
|
||||
buildSingleMetricQuery(k8sPodMemRequestUtilKey, 'mem_request_util'),
|
||||
filesystemUsagePercentQuery,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
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]));
|
||||
});
|
||||
});
|
||||
@@ -1,4 +0,0 @@
|
||||
export const EXPORT_PAGE_SIZE = 50_000;
|
||||
|
||||
/** Pages fetched in parallel.*/
|
||||
export const EXPORT_CONCURRENCY = 3;
|
||||
@@ -1,143 +0,0 @@
|
||||
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],
|
||||
);
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
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 content (string or Blob) as a file. */
|
||||
/** Triggers a browser download of in-memory string content as a file. */
|
||||
export function downloadFile(
|
||||
content: string | Blob,
|
||||
content: string,
|
||||
fileName: string,
|
||||
mime: string,
|
||||
): void {
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
/**
|
||||
* 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',
|
||||
});
|
||||
}
|
||||
@@ -101,10 +101,8 @@ function DashboardActions({
|
||||
|
||||
const handleCreateSection = useCallback(
|
||||
async (title: string): Promise<void> => {
|
||||
const ok = await addSection(title);
|
||||
if (ok) {
|
||||
setIsNewSectionOpen(false);
|
||||
}
|
||||
await addSection(title);
|
||||
setIsNewSectionOpen(false);
|
||||
},
|
||||
[addSection],
|
||||
);
|
||||
|
||||
@@ -100,11 +100,13 @@
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Fixed footprint (2 tags + `+N`): never shrinks, so a long title ellipsizes
|
||||
around it rather than collapsing the tags. */
|
||||
/* Flexes into the remaining space and clips so the ResizeObserver can measure
|
||||
how many tags fit before collapsing the rest into a `+N` badge. */
|
||||
.dashboardTags {
|
||||
display: flex;
|
||||
flex: none;
|
||||
flex: 1 1 0;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -20,13 +20,10 @@ import { linkifyText } from 'utils/linkifyText';
|
||||
import { openInNewTab } from 'utils/navigation';
|
||||
|
||||
import styles from './DashboardInfo.module.scss';
|
||||
import { useVisibleTagCount } from './useVisibleTagCount';
|
||||
import { DASHBOARD_NAME_MAX_LENGTH } from '../../constants';
|
||||
import { useDashboardStore } from '../../store/useDashboardStore';
|
||||
|
||||
// The tag cluster keeps a fixed footprint so a long title ellipsizes around it
|
||||
// instead of collapsing the tags: show up to two tags, then a `+N` overflow badge.
|
||||
const MAX_VISIBLE_TAGS = 2;
|
||||
|
||||
interface DashboardInfoProps {
|
||||
title: string;
|
||||
image: string;
|
||||
@@ -71,8 +68,10 @@ function DashboardInfo({
|
||||
const hasTags = tags.length > 0;
|
||||
const hasDescription = !isEmpty(description);
|
||||
|
||||
const visibleTags = tags.slice(0, MAX_VISIBLE_TAGS);
|
||||
const remainingTags = tags.slice(MAX_VISIBLE_TAGS);
|
||||
const { containerRef, visibleCount } = useVisibleTagCount(tags);
|
||||
const needsOverflow = tags.length > visibleCount;
|
||||
const visibleTags = needsOverflow ? tags.slice(0, visibleCount) : tags;
|
||||
const remainingTags = needsOverflow ? tags.slice(visibleCount) : [];
|
||||
|
||||
let lockTooltip: string;
|
||||
if (onToggleLock) {
|
||||
@@ -226,7 +225,11 @@ function DashboardInfo({
|
||||
{hasTags && (
|
||||
<>
|
||||
<span className={styles.divider} />
|
||||
<div className={styles.dashboardTags} data-testid="dashboard-tags">
|
||||
<div
|
||||
ref={containerRef}
|
||||
className={styles.dashboardTags}
|
||||
data-testid="dashboard-tags"
|
||||
>
|
||||
{visibleTags.map((tag) => (
|
||||
<TagBadge key={tag}>{tag}</TagBadge>
|
||||
))}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import {
|
||||
BADGE_GAP,
|
||||
estimateBadgeWidth,
|
||||
OVERFLOW_BADGE_WIDTH,
|
||||
} from 'components/Alerts/LabelColumn/utils';
|
||||
|
||||
interface Result {
|
||||
containerRef: React.RefObject<HTMLDivElement>;
|
||||
visibleCount: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Measures how many tags fit in the container and returns the visible count,
|
||||
* reserving room for the `+N` overflow badge. Reuses the badge-width estimation
|
||||
* from the alerts LabelColumn so dashboards and alerts overflow identically.
|
||||
*/
|
||||
export function useVisibleTagCount(tags: string[]): Result {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const [visibleCount, setVisibleCount] = useState(tags.length);
|
||||
|
||||
const calculateVisible = useCallback(
|
||||
(width: number): number => {
|
||||
if (width <= 0) {
|
||||
return 1;
|
||||
}
|
||||
const availableWidth = width - OVERFLOW_BADGE_WIDTH - BADGE_GAP;
|
||||
let usedWidth = 0;
|
||||
let count = 0;
|
||||
for (const tag of tags) {
|
||||
const badgeWidth = estimateBadgeWidth(tag) + BADGE_GAP;
|
||||
if (usedWidth + badgeWidth > availableWidth && count > 0) {
|
||||
break;
|
||||
}
|
||||
usedWidth += badgeWidth;
|
||||
count += 1;
|
||||
}
|
||||
return Math.max(1, count);
|
||||
},
|
||||
[tags],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const container = containerRef.current;
|
||||
if (!container) {
|
||||
return undefined;
|
||||
}
|
||||
const observer = new ResizeObserver((entries) => {
|
||||
const entry = entries[0];
|
||||
if (entry && entry.contentRect.width > 0) {
|
||||
setVisibleCount(calculateVisible(entry.contentRect.width));
|
||||
}
|
||||
});
|
||||
observer.observe(container);
|
||||
if (container.clientWidth > 0) {
|
||||
setVisibleCount(calculateVisible(container.clientWidth));
|
||||
}
|
||||
return (): void => observer.disconnect();
|
||||
}, [calculateVisible]);
|
||||
|
||||
return { containerRef, visibleCount };
|
||||
}
|
||||
@@ -78,12 +78,6 @@ function JsonEditorDrawer({
|
||||
const onKeyDown = useCallback(
|
||||
(event: KeyboardEvent<HTMLDivElement>): void => {
|
||||
event.stopPropagation();
|
||||
|
||||
if (event.key === 'Escape') {
|
||||
onClose();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
if (!readOnly) {
|
||||
@@ -91,7 +85,7 @@ function JsonEditorDrawer({
|
||||
}
|
||||
}
|
||||
},
|
||||
[apply, readOnly, onClose],
|
||||
[apply, readOnly],
|
||||
);
|
||||
|
||||
const applyDisabled = readOnly || !isDirty || !validity.valid || isSaving;
|
||||
|
||||
@@ -44,12 +44,8 @@ const dashboard = {
|
||||
},
|
||||
} as unknown as DashboardtypesGettableDashboardV2DTO;
|
||||
|
||||
// The editor exposes `spec`, `tags`, `image` (in that order); every other key is redacted.
|
||||
const redacted = {
|
||||
spec: dashboard.spec,
|
||||
tags: dashboard.tags,
|
||||
image: dashboard.image,
|
||||
};
|
||||
// The editor only exposes `tags` and `spec`; every other key is redacted.
|
||||
const redacted = { tags: dashboard.tags, spec: dashboard.spec };
|
||||
const serialized = JSON.stringify(redacted, null, 2);
|
||||
|
||||
describe('useJsonEditor', () => {
|
||||
@@ -69,18 +65,17 @@ describe('useJsonEditor', () => {
|
||||
expect(result.current.validity.lineCount).toBe(serialized.split('\n').length);
|
||||
});
|
||||
|
||||
it('exposes spec/tags/image (in order) and redacts server-owned keys', () => {
|
||||
it('redacts server-owned keys from the editable draft', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useJsonEditor({ dashboard, isOpen: true, onApplied: jest.fn() }),
|
||||
);
|
||||
|
||||
const parsed = JSON.parse(result.current.draft);
|
||||
// Key order is intentional: spec, then tags, then image.
|
||||
expect(Object.keys(parsed)).toStrictEqual(['spec', 'tags', 'image']);
|
||||
expect(parsed.image).toBe('icon.png');
|
||||
expect(Object.keys(parsed).sort()).toStrictEqual(['spec', 'tags']);
|
||||
expect(parsed.id).toBeUndefined();
|
||||
expect(parsed.name).toBeUndefined();
|
||||
expect(parsed.schemaVersion).toBeUndefined();
|
||||
expect(parsed.image).toBeUndefined();
|
||||
});
|
||||
|
||||
it('flags invalid JSON with a line number and marks the draft dirty', () => {
|
||||
|
||||
@@ -12,7 +12,6 @@ import { toAPIError } from 'utils/errorUtils';
|
||||
|
||||
import { dashboardToUpdatable } from './dashboardToUpdatable';
|
||||
import { findPanelLayoutIssues } from './danglingPanels';
|
||||
import { compactSpecLayouts } from '../../layoutCompaction';
|
||||
import { useDashboardStore } from '../../store/useDashboardStore';
|
||||
|
||||
export interface JsonValidity {
|
||||
@@ -47,16 +46,15 @@ interface Result {
|
||||
}
|
||||
|
||||
/**
|
||||
* The editable, user-facing view: `spec`, `tags` and `image`, in that key order.
|
||||
* Everything else (id, orgId, name, timestamps, locked, schemaVersion, …) is redacted
|
||||
* so it can't be seen, copied, exported or edited; those keys are preserved on save.
|
||||
* The editable, user-facing view: only `tags` and `spec`. Everything else
|
||||
* (id, orgId, name, timestamps, locked, schemaVersion, image, …) is redacted so it
|
||||
* can't be seen, copied, exported or edited; those keys are preserved on save (see `apply`).
|
||||
*/
|
||||
const redact = (
|
||||
dashboard: DashboardtypesGettableDashboardV2DTO,
|
||||
): Pick<DashboardtypesGettableDashboardV2DTO, 'spec' | 'tags' | 'image'> => ({
|
||||
spec: dashboard.spec,
|
||||
): Pick<DashboardtypesGettableDashboardV2DTO, 'tags' | 'spec'> => ({
|
||||
tags: dashboard.tags,
|
||||
image: dashboard.image,
|
||||
spec: dashboard.spec,
|
||||
});
|
||||
|
||||
const serialize = (dashboard: DashboardtypesGettableDashboardV2DTO): string =>
|
||||
@@ -169,18 +167,7 @@ export function useJsonEditor({
|
||||
setIsSaving(true);
|
||||
// The draft only carries name/tags/spec; overlay it on the current dashboard
|
||||
// so the redacted fields (schemaVersion, image, …) are preserved on save.
|
||||
const edited = JSON.parse(draft) as Pick<
|
||||
DashboardtypesGettableDashboardV2DTO,
|
||||
'spec' | 'tags' | 'image'
|
||||
>;
|
||||
// Snap hand-edited panel geometry to a non-overlapping layout so a JSON edit
|
||||
// can't be rejected by the backend's no-overlap check (matches drag/resize).
|
||||
if (edited.spec?.layouts) {
|
||||
edited.spec = {
|
||||
...edited.spec,
|
||||
layouts: compactSpecLayouts(edited.spec.layouts),
|
||||
};
|
||||
}
|
||||
const edited = JSON.parse(draft) as Record<string, unknown>;
|
||||
await updateDashboardV2(
|
||||
{ id: dashboardId },
|
||||
dashboardToUpdatable({ ...dashboard, ...edited }),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -27,28 +26,11 @@ function DashboardImagePicker({
|
||||
onChange,
|
||||
triggerClassName,
|
||||
}: Props): JSX.Element {
|
||||
// A custom image (pasted URL / base64 data-URI, not in the preset set) is kept as
|
||||
// a selectable option for the picker's lifetime — without a matching option the
|
||||
// trigger renders the raw value string and the image can't be re-selected.
|
||||
const [customImages, setCustomImages] = useState<string[]>(() =>
|
||||
image && !Base64Icons.includes(image) ? [image] : [],
|
||||
);
|
||||
useEffect(() => {
|
||||
if (image && !Base64Icons.includes(image)) {
|
||||
setCustomImages((prev) => (prev.includes(image) ? prev : [...prev, image]));
|
||||
}
|
||||
}, [image]);
|
||||
|
||||
const options = useMemo(
|
||||
() => [...customImages, ...Base64Icons],
|
||||
[customImages],
|
||||
);
|
||||
|
||||
return (
|
||||
<Select value={image} onChange={(value): void => onChange(value as string)}>
|
||||
<SelectTrigger className={cx(styles.trigger, triggerClassName)} />
|
||||
<SelectContent className={styles.options} withPortal={false}>
|
||||
{options.map((icon) => (
|
||||
{Base64Icons.map((icon) => (
|
||||
<SelectItem key={icon} value={icon} className={styles.item}>
|
||||
<img src={icon} alt="dashboard-icon" className={styles.image} />
|
||||
</SelectItem>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
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';
|
||||
@@ -15,16 +14,17 @@ 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: DashboardtypesDynamicVariableSignalDTO;
|
||||
signal: DynamicSignalOption;
|
||||
onChange: (patch: {
|
||||
dynamicAttribute?: string;
|
||||
dynamicSignal?: DashboardtypesDynamicVariableSignalDTO;
|
||||
dynamicSignal?: DynamicSignalOption;
|
||||
}) => void;
|
||||
onPreview: (values: (string | number)[]) => void;
|
||||
/** Inline error shown under the attribute field (e.g. duplicate attribute). */
|
||||
@@ -117,9 +117,7 @@ function DynamicVariableFields({
|
||||
value: s,
|
||||
}))}
|
||||
onChange={(value): void =>
|
||||
onChange({
|
||||
dynamicSignal: value as DashboardtypesDynamicVariableSignalDTO,
|
||||
})
|
||||
onChange({ dynamicSignal: value as DynamicSignalOption })
|
||||
}
|
||||
data-testid="variable-signal-select"
|
||||
/>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
@@ -27,7 +27,6 @@ function QueryVariableFields({
|
||||
onError,
|
||||
}: QueryVariableFieldsProps): JSX.Element {
|
||||
const [isRunning, setIsRunning] = useState(false);
|
||||
const hasAutoRun = useRef(false);
|
||||
|
||||
const runTest = async (): Promise<void> => {
|
||||
setIsRunning(true);
|
||||
@@ -60,16 +59,6 @@ function QueryVariableFields({
|
||||
}
|
||||
};
|
||||
|
||||
// Fetch options on load so the Default Value dropdown is populated without a
|
||||
// manual Test Run — once, and only when there's a query to run.
|
||||
useEffect(() => {
|
||||
if (!hasAutoRun.current && queryValue) {
|
||||
hasAutoRun.current = true;
|
||||
void runTest();
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [queryValue]);
|
||||
|
||||
return (
|
||||
<div className={styles.queryContainer}>
|
||||
<div className={styles.labelContainer}>
|
||||
|
||||
@@ -160,26 +160,6 @@
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* The full "Not Recommended" pill — hidden once the tab row gets tight so it
|
||||
never forces horizontal scroll; the amber info icon takes over below. */
|
||||
.notRecommendedBadge {
|
||||
margin-left: 4px;
|
||||
vertical-align: middle;
|
||||
|
||||
@media (max-width: 1280px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Amber info icon: always present, but the sole "not recommended" cue on small
|
||||
screens (its tooltip carries the message + learn-more link). */
|
||||
.notRecommendedInfo {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-left: 4px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* Query */
|
||||
.queryContainer {
|
||||
display: flex;
|
||||
|
||||
@@ -130,9 +130,6 @@ function VariableForm({
|
||||
value={selectedPanelIds}
|
||||
onChange={(value): void => setSelectedPanelIds(value as string[])}
|
||||
data-testid="variable-apply-panels"
|
||||
// Resolve the closed-state tags to panel names (else they show the id).
|
||||
showLabels
|
||||
placement="topRight"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -218,7 +215,7 @@ function VariableForm({
|
||||
variant="solid"
|
||||
color="primary"
|
||||
prefix={<Check size={14} />}
|
||||
disabled={!!nameError || !!attributeError || isSaving}
|
||||
disabled={!!nameError || !!attributeError}
|
||||
loading={isSaving}
|
||||
onClick={handleSave}
|
||||
testId="variable-save"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import {
|
||||
ClipboardType,
|
||||
DatabaseZap,
|
||||
@@ -68,23 +67,20 @@ function VariableTypeTabs(): JSX.Element {
|
||||
>
|
||||
<DatabaseZap size={14} />
|
||||
Query
|
||||
{/* Wide screens: the full "Not Recommended" pill. */}
|
||||
<Badge color="amber" className={styles.notRecommendedBadge}>
|
||||
<Badge color="amber" className={styles.betaTag}>
|
||||
Not Recommended
|
||||
</Badge>
|
||||
{/* Small screens: an amber info icon stands in for the pill (keeps the
|
||||
tab row from overflowing), its tooltip carries the same message + link. */}
|
||||
<span
|
||||
className={styles.notRecommendedInfo}
|
||||
className={styles.betaTag}
|
||||
onClick={(e): void => e.stopPropagation()}
|
||||
role="presentation"
|
||||
>
|
||||
<TextToolTip
|
||||
text="Query variables can be slow and brittle, so they aren't recommended. Learn why"
|
||||
text="Learn why we don't recommend"
|
||||
url="https://signoz.io/docs/userguide/manage-variables/#why-avoid-clickhouse-query-variables"
|
||||
urlText="here"
|
||||
useFilledIcon={false}
|
||||
outlinedIcon={<Info size={14} color={Color.BG_AMBER_600} />}
|
||||
outlinedIcon={<Info size={14} />}
|
||||
/>
|
||||
</span>
|
||||
</TabsTrigger>
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
import { act, renderHook, type RenderHookResult } from '@testing-library/react';
|
||||
|
||||
import {
|
||||
DYNAMIC_SIGNALS,
|
||||
emptyVariableFormModel,
|
||||
VARIABLE_SORT,
|
||||
type VariableFormModel,
|
||||
} from '../variableFormModel';
|
||||
import { useVariableForm, type UseVariableForm } from './useVariableForm';
|
||||
|
||||
// Mock the store (its full slice graph is huge to transform and irrelevant here;
|
||||
// the hook only reads dashboardId + variableValues for the Test-Run payload).
|
||||
jest.mock('../../../store/useDashboardStore', () => ({
|
||||
useDashboardStore: (selector: (state: unknown) => unknown): unknown =>
|
||||
selector({ dashboardId: undefined, variableValues: {} }),
|
||||
}));
|
||||
|
||||
function initial(overrides?: Partial<VariableFormModel>): VariableFormModel {
|
||||
return {
|
||||
...emptyVariableFormModel(),
|
||||
type: 'QUERY',
|
||||
name: 'svc',
|
||||
defaultValue: 'foo',
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
const args = (
|
||||
init: VariableFormModel,
|
||||
): Parameters<typeof useVariableForm>[0] => ({
|
||||
initial: init,
|
||||
siblings: [],
|
||||
isNew: false,
|
||||
onSave: jest.fn(),
|
||||
});
|
||||
|
||||
// The hook resets its form state whenever the `initial` reference changes (open a
|
||||
// different variable), so the args must be stable across re-renders — otherwise a
|
||||
// fresh `initial` each render would loop the reset effect. Real callers memoize
|
||||
// `initial`; mirror that here by building the props once and closing over them.
|
||||
const renderForm = (
|
||||
props: Parameters<typeof useVariableForm>[0],
|
||||
): RenderHookResult<UseVariableForm, unknown> =>
|
||||
renderHook(() => useVariableForm(props));
|
||||
|
||||
describe('useVariableForm default reset — QUERY (on Test Run)', () => {
|
||||
it('keeps the default when only the sort order changes', () => {
|
||||
const { result } = renderForm(args(initial()));
|
||||
|
||||
act(() => result.current.setRawPreview(['foo', 'bar']));
|
||||
expect(result.current.defaultValue).toBe('foo');
|
||||
|
||||
// order-only change doesn't touch the preview values, so it must not reset
|
||||
act(() => result.current.set({ sort: VARIABLE_SORT.DESC }));
|
||||
expect(result.current.defaultValue).toBe('foo');
|
||||
});
|
||||
|
||||
it('resets the default when a Test Run returns values that no longer contain it', () => {
|
||||
const { result } = renderForm(args(initial()));
|
||||
|
||||
act(() => result.current.setRawPreview(['foo', 'bar']));
|
||||
expect(result.current.defaultValue).toBe('foo');
|
||||
|
||||
act(() => result.current.setRawPreview(['bar', 'baz']));
|
||||
expect(result.current.defaultValue).toBe('');
|
||||
});
|
||||
|
||||
it('keeps the default when a Test Run still contains it', () => {
|
||||
const { result } = renderForm(args(initial()));
|
||||
|
||||
act(() => result.current.setRawPreview(['foo', 'bar']));
|
||||
act(() => result.current.setRawPreview(['foo', 'baz', 'qux']));
|
||||
expect(result.current.defaultValue).toBe('foo');
|
||||
});
|
||||
|
||||
it('keeps the default when a re-run yields the same values (no actual change)', () => {
|
||||
const { result } = renderForm(args(initial({ defaultValue: 'bar' })));
|
||||
|
||||
act(() => result.current.setRawPreview(['foo', 'bar']));
|
||||
// same set again — re-running an unchanged query must not disturb the default
|
||||
act(() => result.current.setRawPreview(['foo', 'bar']));
|
||||
expect(result.current.defaultValue).toBe('bar');
|
||||
});
|
||||
});
|
||||
|
||||
describe('useVariableForm default reset — DYNAMIC (on attribute/signal change)', () => {
|
||||
const dynamic = (overrides?: Partial<VariableFormModel>): VariableFormModel =>
|
||||
initial({
|
||||
type: 'DYNAMIC',
|
||||
dynamicAttribute: 'service.name',
|
||||
dynamicSignal: DYNAMIC_SIGNALS[1],
|
||||
...overrides,
|
||||
});
|
||||
|
||||
it('does not reset on the passive edit-open auto-fetch', () => {
|
||||
// The auto-fetch populates the preview without going through onDynamicChange,
|
||||
// so opening an existing variable must never clear its saved default.
|
||||
const { result } = renderForm(args(dynamic({ defaultValue: 'zzz' })));
|
||||
|
||||
act(() => result.current.setRawPreview(['foo', 'bar']));
|
||||
expect(result.current.defaultValue).toBe('zzz');
|
||||
});
|
||||
|
||||
it('resets when the attribute changes', () => {
|
||||
const { result } = renderForm(args(dynamic()));
|
||||
|
||||
act(() => result.current.onDynamicChange({ dynamicAttribute: 'host.name' }));
|
||||
expect(result.current.defaultValue).toBe('');
|
||||
});
|
||||
|
||||
it('resets when the signal changes', () => {
|
||||
const { result } = renderForm(args(dynamic()));
|
||||
|
||||
act(() =>
|
||||
result.current.onDynamicChange({ dynamicSignal: DYNAMIC_SIGNALS[2] }),
|
||||
);
|
||||
expect(result.current.defaultValue).toBe('');
|
||||
});
|
||||
|
||||
it('keeps the default when the attribute is set to the same value', () => {
|
||||
const { result } = renderForm(args(dynamic()));
|
||||
|
||||
act(() =>
|
||||
result.current.onDynamicChange({ dynamicAttribute: 'service.name' }),
|
||||
);
|
||||
expect(result.current.defaultValue).toBe('foo');
|
||||
});
|
||||
});
|
||||
|
||||
describe('useVariableForm default reset — CUSTOM (on options edit)', () => {
|
||||
const custom = (overrides?: Partial<VariableFormModel>): VariableFormModel =>
|
||||
initial({ type: 'CUSTOM', ...overrides });
|
||||
|
||||
it('resets when the edited options no longer contain the default', () => {
|
||||
const { result } = renderForm(args(custom()));
|
||||
|
||||
act(() => result.current.onCustomChange('bar, baz'));
|
||||
expect(result.current.defaultValue).toBe('');
|
||||
});
|
||||
|
||||
it('keeps the default when the edited options still contain it', () => {
|
||||
const { result } = renderForm(args(custom()));
|
||||
|
||||
act(() => result.current.onCustomChange('foo, bar, baz'));
|
||||
expect(result.current.defaultValue).toBe('foo');
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { commaValuesParser } from 'lib/dashboardVariables/customCommaValuesParser';
|
||||
import { DashboardDetailEvents } from 'pages/DashboardPageV2/constants/events';
|
||||
@@ -92,35 +92,6 @@ export function useVariableForm({
|
||||
[rawPreview, model.sort],
|
||||
);
|
||||
|
||||
// QUERY: drop a now-invalid default when the user re-runs the query and the
|
||||
// returned values actually change. The query preview is populated only by the
|
||||
// manual "Test Run" (never on edit-open), so keying off `rawPreview` here is
|
||||
// effectively "on run"; the signature guard skips a re-run that yields the same
|
||||
// values so a still-valid default is left untouched. DYNAMIC/CUSTOM resets are
|
||||
// handled in their change handlers instead (see below).
|
||||
const lastQueryPreviewRef = useRef<string | null>(null);
|
||||
useEffect(() => {
|
||||
lastQueryPreviewRef.current = null;
|
||||
}, [initial]);
|
||||
|
||||
useEffect(() => {
|
||||
if (model.type !== 'QUERY' || rawPreview.length === 0) {
|
||||
return;
|
||||
}
|
||||
const optionValues = rawPreview.map(String);
|
||||
const signature = JSON.stringify(optionValues);
|
||||
if (signature === lastQueryPreviewRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastQueryPreviewRef.current = signature;
|
||||
|
||||
// Clear a now-invalid default; resolution falls back to the first option/ALL.
|
||||
setDefaultValue((current) =>
|
||||
current && !optionValues.includes(current) ? '' : current,
|
||||
);
|
||||
}, [rawPreview, model.type]);
|
||||
|
||||
const existingNames = useMemo(() => siblings.map((v) => v.name), [siblings]);
|
||||
|
||||
const existingDynamicAttributes = useMemo(
|
||||
@@ -169,28 +140,12 @@ export function useVariableForm({
|
||||
|
||||
const onCustomChange = (value: string): void => {
|
||||
set({ customValue: value });
|
||||
const parsed = commaValuesParser(value);
|
||||
setRawPreview(parsed);
|
||||
|
||||
const optionValues = parsed.map(String);
|
||||
setDefaultValue((current) =>
|
||||
current && !optionValues.includes(current) ? '' : current,
|
||||
);
|
||||
setRawPreview(commaValuesParser(value));
|
||||
};
|
||||
|
||||
// In add mode, mirror the selected attribute into the name until the user
|
||||
// edits the name themselves (matches the V1 dynamic-variable behaviour).
|
||||
const onDynamicChange = (patch: Partial<VariableFormModel>): void => {
|
||||
const attributeChanged =
|
||||
patch.dynamicAttribute !== undefined &&
|
||||
patch.dynamicAttribute !== model.dynamicAttribute;
|
||||
const signalChanged =
|
||||
patch.dynamicSignal !== undefined &&
|
||||
patch.dynamicSignal !== model.dynamicSignal;
|
||||
if (attributeChanged || signalChanged) {
|
||||
setDefaultValue('');
|
||||
}
|
||||
|
||||
if (isNew && !nameTouched && patch.dynamicAttribute) {
|
||||
set({ ...patch, name: patch.dynamicAttribute });
|
||||
} else {
|
||||
|
||||
@@ -54,18 +54,11 @@ function VariableImpactDialog({
|
||||
useVariableImpactState(usages, open);
|
||||
|
||||
const isRename = mode === 'rename';
|
||||
const isDelete = mode === 'delete';
|
||||
const count = usages.length;
|
||||
const plural = count === 1 ? '' : 's';
|
||||
let intro: string;
|
||||
if (isRename) {
|
||||
intro = `$${variableName} is used in ${count} place${plural}. Review the updated queries before renaming to $${newName}.`;
|
||||
} else if (isDelete) {
|
||||
intro = `$${variableName} is used in ${count} place${plural}. Edit or remove each usage before deleting.`;
|
||||
} else {
|
||||
intro = `Applying $${variableName} can update upto ${count} panel quer${count === 1 ? 'y' : 'ies'}. Review the changes before applying.`;
|
||||
}
|
||||
const confirmLabel = isRename ? 'Rename' : isDelete ? 'Delete' : 'Apply';
|
||||
const intro = isRename
|
||||
? `$${variableName} is used in ${count} place${plural}. Review the updated queries before renaming to $${newName}.`
|
||||
: `$${variableName} is used in ${count} place${plural}. Edit or remove each usage before deleting.`;
|
||||
|
||||
const footer = (
|
||||
<div className={styles.footer}>
|
||||
@@ -80,13 +73,13 @@ function VariableImpactDialog({
|
||||
</Button>
|
||||
<Button
|
||||
variant="solid"
|
||||
color={isDelete ? 'destructive' : 'primary'}
|
||||
color={isRename ? 'primary' : 'destructive'}
|
||||
loading={isLoading}
|
||||
onClick={(): void => onConfirm(resolvedUsages)}
|
||||
testId="variable-impact-confirm"
|
||||
>
|
||||
<Check size={12} />
|
||||
{confirmLabel}
|
||||
{isRename ? 'Rename' : 'Delete'}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
@@ -99,14 +92,7 @@ function VariableImpactDialog({
|
||||
onClose();
|
||||
}
|
||||
}}
|
||||
title={
|
||||
// eslint-disable-next-line no-nested-ternary
|
||||
isRename
|
||||
? `Rename $${variableName}`
|
||||
: isDelete
|
||||
? `Delete $${variableName}`
|
||||
: `Apply $${variableName} to panels`
|
||||
}
|
||||
title={isRename ? `Rename $${variableName}` : `Delete $${variableName}`}
|
||||
width="wide"
|
||||
showCloseButton={false}
|
||||
// Lift above the settings drawer (z ~1000); overlay off (it would only half-dim).
|
||||
@@ -118,9 +104,7 @@ function VariableImpactDialog({
|
||||
<Typography.Text className={styles.intro}>{intro}</Typography.Text>
|
||||
<div className={styles.rows}>
|
||||
{rows.map((row) => {
|
||||
// Only warn on delete: an apply result is meant to reference the variable.
|
||||
const stillReferences =
|
||||
isDelete &&
|
||||
row.included &&
|
||||
textContainsVariableReference(row.resultingText, variableName);
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
import type { DashboardtypesDashboardSpecDTOPanels } from 'api/generated/services/sigNoz.schemas';
|
||||
import type {
|
||||
DashboardtypesDashboardSpecDTOPanels,
|
||||
DashboardtypesJSONPatchOperationDTO,
|
||||
} from 'api/generated/services/sigNoz.schemas';
|
||||
|
||||
import { getPanelIdsReferencingVariable } from '../utils/applyVariableToPanelsPatch';
|
||||
import {
|
||||
buildApplyVariableToPanelsPatch,
|
||||
buildSyncVariableToPanelsPatch,
|
||||
getPanelIdsReferencingVariable,
|
||||
} from '../utils/applyVariableToPanelsPatch';
|
||||
|
||||
/** Minimal builder-query panel wrapped in a CompositeQuery, with a given filter. */
|
||||
function compositePanel(filterExpression: string): unknown {
|
||||
@@ -61,12 +68,153 @@ function listPanel(filterExpression: string): unknown {
|
||||
};
|
||||
}
|
||||
|
||||
/** A PromQL panel — no builder filter, must be skipped. */
|
||||
function promqlPanel(): unknown {
|
||||
return {
|
||||
kind: 'panel',
|
||||
spec: {
|
||||
display: { title: '' },
|
||||
plugin: { kind: 'signoz/TimeSeries', spec: {} },
|
||||
queries: [
|
||||
{
|
||||
kind: 'promql',
|
||||
spec: {
|
||||
plugin: { kind: 'signoz/PromQLQuery', spec: { query: 'up' } },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/** Reads the first builder query's filter expression out of a patch op's value. */
|
||||
function expressionOf(
|
||||
op: DashboardtypesJSONPatchOperationDTO,
|
||||
): string | undefined {
|
||||
const queries = op.value as Array<{
|
||||
spec: { plugin: { kind: string; spec: any } };
|
||||
}>;
|
||||
const { plugin } = queries[0].spec;
|
||||
const builderSpec =
|
||||
plugin.kind === 'signoz/CompositeQuery'
|
||||
? plugin.spec.queries[0].spec
|
||||
: plugin.spec;
|
||||
return builderSpec.filter?.expression;
|
||||
}
|
||||
|
||||
function panels(
|
||||
map: Record<string, unknown>,
|
||||
): DashboardtypesDashboardSpecDTOPanels {
|
||||
return map as DashboardtypesDashboardSpecDTOPanels;
|
||||
}
|
||||
|
||||
describe('buildApplyVariableToPanelsPatch', () => {
|
||||
it('appends the clause to an existing filter (AND-joined)', () => {
|
||||
const ops = buildApplyVariableToPanelsPatch(
|
||||
panels({ p1: compositePanel('env = "prod"') }),
|
||||
'service.name',
|
||||
'svc',
|
||||
);
|
||||
expect(ops).toHaveLength(1);
|
||||
expect(ops[0]).toMatchObject({
|
||||
op: 'replace',
|
||||
path: '/spec/panels/p1/spec/queries',
|
||||
});
|
||||
expect(expressionOf(ops[0])).toBe('env = "prod" AND service.name IN $svc');
|
||||
});
|
||||
|
||||
it('sets the clause when the filter is empty', () => {
|
||||
const ops = buildApplyVariableToPanelsPatch(
|
||||
panels({ p1: compositePanel('') }),
|
||||
'service.name',
|
||||
'svc',
|
||||
);
|
||||
expect(expressionOf(ops[0])).toBe('service.name IN $svc');
|
||||
});
|
||||
|
||||
it('applies to a bare BuilderQuery (LIST) panel', () => {
|
||||
const ops = buildApplyVariableToPanelsPatch(
|
||||
panels({ p1: listPanel('') }),
|
||||
'k8s.pod.name',
|
||||
'pod',
|
||||
);
|
||||
expect(expressionOf(ops[0])).toBe('k8s.pod.name IN $pod');
|
||||
});
|
||||
|
||||
it('is idempotent — re-applying does not duplicate the clause', () => {
|
||||
const ops = buildApplyVariableToPanelsPatch(
|
||||
panels({ p1: compositePanel('service.name IN $svc') }),
|
||||
'service.name',
|
||||
'svc',
|
||||
);
|
||||
expect(ops).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('only targets the requested panels', () => {
|
||||
const ops = buildApplyVariableToPanelsPatch(
|
||||
panels({ p1: compositePanel(''), p2: compositePanel('') }),
|
||||
'service.name',
|
||||
'svc',
|
||||
['p2'],
|
||||
);
|
||||
expect(ops).toHaveLength(1);
|
||||
expect(ops[0].path).toBe('/spec/panels/p2/spec/queries');
|
||||
});
|
||||
|
||||
it('skips PromQL panels (no builder filter)', () => {
|
||||
const ops = buildApplyVariableToPanelsPatch(
|
||||
panels({ p1: promqlPanel() }),
|
||||
'service.name',
|
||||
'svc',
|
||||
);
|
||||
expect(ops).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('returns nothing when attribute or name is missing', () => {
|
||||
expect(
|
||||
buildApplyVariableToPanelsPatch(
|
||||
panels({ p1: compositePanel('') }),
|
||||
'',
|
||||
'svc',
|
||||
),
|
||||
).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildSyncVariableToPanelsPatch', () => {
|
||||
it('adds to selected panels and removes from the rest', () => {
|
||||
const ops = buildSyncVariableToPanelsPatch(
|
||||
panels({
|
||||
p1: compositePanel('service.name IN $svc'), // has it, not selected → remove
|
||||
p2: compositePanel(''), // selected → add
|
||||
p3: compositePanel('service.name IN $svc'), // has it, selected → unchanged
|
||||
}),
|
||||
'service.name',
|
||||
'svc',
|
||||
['p2', 'p3'],
|
||||
);
|
||||
const byPath = Object.fromEntries(ops.map((op) => [op.path, op]));
|
||||
expect(Object.keys(byPath).sort()).toStrictEqual([
|
||||
'/spec/panels/p1/spec/queries',
|
||||
'/spec/panels/p2/spec/queries',
|
||||
]);
|
||||
expect(expressionOf(byPath['/spec/panels/p1/spec/queries'])).toBe('');
|
||||
expect(expressionOf(byPath['/spec/panels/p2/spec/queries'])).toBe(
|
||||
'service.name IN $svc',
|
||||
);
|
||||
});
|
||||
|
||||
it('removing keeps other clauses intact', () => {
|
||||
const ops = buildSyncVariableToPanelsPatch(
|
||||
panels({ p1: compositePanel('env = "prod" AND service.name IN $svc') }),
|
||||
'service.name',
|
||||
'svc',
|
||||
[],
|
||||
);
|
||||
expect(expressionOf(ops[0])).toBe('env = "prod"');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getPanelIdsReferencingVariable', () => {
|
||||
it('returns only panels whose filter references the variable', () => {
|
||||
const ids = getPanelIdsReferencingVariable(
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import type { DashboardtypesGettableDashboardV2DTO } from 'api/generated/services/sigNoz.schemas';
|
||||
|
||||
import { useVariableListActions } from '../hooks/useVariableListActions';
|
||||
import {
|
||||
emptyVariableFormModel,
|
||||
type VariableFormModel,
|
||||
} from '../variableFormModel';
|
||||
|
||||
jest.mock('../../../store/useDashboardStore', () => ({
|
||||
useDashboardStore: (
|
||||
selector: (s: { dashboardId: string }) => unknown,
|
||||
): unknown => selector({ dashboardId: 'd1' }),
|
||||
}));
|
||||
jest.mock('api/common/logEvent', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn(),
|
||||
}));
|
||||
jest.mock('@signozhq/ui/sonner', () => ({
|
||||
toast: { success: jest.fn(), error: jest.fn(), info: jest.fn() },
|
||||
}));
|
||||
|
||||
function builderPanel(name: string, expression: string): unknown {
|
||||
return {
|
||||
spec: {
|
||||
display: { name },
|
||||
queries: [
|
||||
{
|
||||
spec: {
|
||||
plugin: { kind: 'signoz/BuilderQuery', spec: { filter: { expression } } },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function dashboard(
|
||||
panels: Record<string, unknown>,
|
||||
): DashboardtypesGettableDashboardV2DTO {
|
||||
return {
|
||||
spec: { panels, variables: [] },
|
||||
} as unknown as DashboardtypesGettableDashboardV2DTO;
|
||||
}
|
||||
|
||||
function dynamicVar(name: string, attribute: string): VariableFormModel {
|
||||
return {
|
||||
...emptyVariableFormModel(),
|
||||
name,
|
||||
type: 'DYNAMIC',
|
||||
dynamicAttribute: attribute,
|
||||
};
|
||||
}
|
||||
|
||||
function renderActions(
|
||||
dash: DashboardtypesGettableDashboardV2DTO,
|
||||
variables: VariableFormModel[],
|
||||
) {
|
||||
return renderHook(() =>
|
||||
useVariableListActions({
|
||||
dashboard: dash,
|
||||
variables,
|
||||
setVariables: jest.fn(),
|
||||
isEditing: null,
|
||||
setIsEditing: jest.fn(),
|
||||
save: jest.fn().mockResolvedValue(true),
|
||||
patchAsync: jest.fn().mockResolvedValue(undefined),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
describe('useVariableListActions — apply to all', () => {
|
||||
it('marks a variable applied-to-all only when every panel already references it', () => {
|
||||
const notApplied = renderActions(dashboard({ p1: builderPanel('P1', '') }), [
|
||||
dynamicVar('pod', 'k8s.pod.name'),
|
||||
]);
|
||||
expect(notApplied.result.current.appliedToAllNames.has('pod')).toBe(false);
|
||||
|
||||
const applied = renderActions(
|
||||
dashboard({ p1: builderPanel('P1', 'k8s.pod.name IN $pod') }),
|
||||
[dynamicVar('pod', 'k8s.pod.name')],
|
||||
);
|
||||
expect(applied.result.current.appliedToAllNames.has('pod')).toBe(true);
|
||||
});
|
||||
|
||||
it('requestApplyToAll opens an apply-mode impact for all panels', () => {
|
||||
const { result } = renderActions(
|
||||
dashboard({ p1: builderPanel('P1', ''), p2: builderPanel('P2', '') }),
|
||||
[dynamicVar('pod', 'k8s.pod.name')],
|
||||
);
|
||||
|
||||
act(() => result.current.requestApplyToAll(0));
|
||||
|
||||
const { impact } = result.current;
|
||||
expect(impact?.mode).toBe('apply');
|
||||
expect(impact?.origin).toBe('applyToAll');
|
||||
expect(impact?.variableName).toBe('pod');
|
||||
expect(impact?.usages.map((u) => u.sourceId).sort()).toStrictEqual([
|
||||
'p1',
|
||||
'p2',
|
||||
]);
|
||||
});
|
||||
|
||||
it('requestApplyToAll is a no-op when nothing is left to apply', () => {
|
||||
const { result } = renderActions(
|
||||
dashboard({ p1: builderPanel('P1', 'k8s.pod.name IN $pod') }),
|
||||
[dynamicVar('pod', 'k8s.pod.name')],
|
||||
);
|
||||
|
||||
act(() => result.current.requestApplyToAll(0));
|
||||
expect(result.current.impact).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -4,11 +4,7 @@ import {
|
||||
emptyVariableFormModel,
|
||||
type VariableFormModel,
|
||||
} from '../variableFormModel';
|
||||
import {
|
||||
findApplyUsages,
|
||||
findVariableUsages,
|
||||
isVariableAppliedToAllPanels,
|
||||
} from '../utils/variableUsages';
|
||||
import { findVariableUsages } from '../utils/variableUsages';
|
||||
|
||||
// Identity adapter so `spec.variables` can be plain form models in the test.
|
||||
jest.mock('../variableAdapters', () => ({
|
||||
@@ -100,98 +96,3 @@ describe('findVariableUsages', () => {
|
||||
expect(findVariableUsages(dash, 'nope', 'delete')).toStrictEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findApplyUsages', () => {
|
||||
const dash = dashboard(
|
||||
{
|
||||
empty: builderPanel('Empty', ''),
|
||||
ored: builderPanel('Ored', "a = 'x' OR b = 'y'"),
|
||||
has: builderPanel('Has it', 'k8s.pod.name IN $pod'),
|
||||
prom: promqlPanel('Prom', 'up'),
|
||||
promRef: promqlPanel('Prom Ref', 'up{pod="$pod"}'),
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
it('appends the clause to selected builder panels, parenthesising an OR', () => {
|
||||
const usages = findApplyUsages(dash, 'k8s.pod.name', 'pod', 'pod', [
|
||||
'empty',
|
||||
'ored',
|
||||
]);
|
||||
const byId = Object.fromEntries(usages.map((u) => [u.id, u.resultingText]));
|
||||
expect(byId['panel:empty:0']).toBe('k8s.pod.name IN $pod');
|
||||
expect(byId['panel:ored:0']).toBe(
|
||||
"(a = 'x' OR b = 'y') AND k8s.pod.name IN $pod",
|
||||
);
|
||||
});
|
||||
|
||||
it('skips a selected panel that already carries the clause (idempotent)', () => {
|
||||
const usages = findApplyUsages(dash, 'k8s.pod.name', 'pod', 'pod', ['has']);
|
||||
expect(usages).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('removes the clause from an unselected builder panel that has it', () => {
|
||||
const usages = findApplyUsages(dash, 'k8s.pod.name', 'pod', 'pod', ['empty']);
|
||||
const has = usages.find((u) => u.id === 'panel:has:0');
|
||||
expect(has?.resultingText).toBe('');
|
||||
});
|
||||
|
||||
it('lists a selected PromQL panel as an editable, unchanged row', () => {
|
||||
const usages = findApplyUsages(dash, 'k8s.pod.name', 'pod', 'pod', ['prom']);
|
||||
const prom = usages.find((u) => u.id === 'panel:prom:0');
|
||||
expect(prom?.kind).toBe('promql');
|
||||
// Never auto-injected — the row defaults to the current text for manual edits.
|
||||
expect(prom?.currentText).toBe('up');
|
||||
expect(prom?.resultingText).toBe('up');
|
||||
});
|
||||
|
||||
it('skips a selected non-builder panel that already references the variable', () => {
|
||||
const usages = findApplyUsages(dash, 'k8s.pod.name', 'pod', 'pod', [
|
||||
'promRef',
|
||||
]);
|
||||
expect(usages.some((u) => u.sourceId === 'promRef')).toBe(false);
|
||||
});
|
||||
|
||||
it('never touches unselected non-builder panels', () => {
|
||||
const usages = findApplyUsages(dash, 'k8s.pod.name', 'pod', 'pod', ['empty']);
|
||||
expect(usages.some((u) => u.sourceId === 'prom')).toBe(false);
|
||||
expect(usages.some((u) => u.sourceId === 'promRef')).toBe(false);
|
||||
});
|
||||
|
||||
it('returns nothing when every selected query already references the variable', () => {
|
||||
// The "applied to all" signal: builder carries the clause, PromQL references it.
|
||||
const usages = findApplyUsages(dash, 'k8s.pod.name', 'pod', 'pod', [
|
||||
'has',
|
||||
'promRef',
|
||||
]);
|
||||
expect(usages).toStrictEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isVariableAppliedToAllPanels', () => {
|
||||
it('is true only when every panel query references the variable', () => {
|
||||
const covered = dashboard(
|
||||
{
|
||||
b: builderPanel('B', 'k8s.pod.name IN $pod'),
|
||||
p: promqlPanel('P', 'up{pod="$pod"}'),
|
||||
},
|
||||
[],
|
||||
);
|
||||
expect(isVariableAppliedToAllPanels(covered, 'k8s.pod.name', 'pod')).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
it('is false when any panel query is missing the reference', () => {
|
||||
const missing = dashboard(
|
||||
{
|
||||
b: builderPanel('B', 'k8s.pod.name IN $pod'),
|
||||
p: promqlPanel('P', 'up'),
|
||||
},
|
||||
[],
|
||||
);
|
||||
expect(isVariableAppliedToAllPanels(missing, 'k8s.pod.name', 'pod')).toBe(
|
||||
false,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
.body {
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
color: var(--l2-foreground);
|
||||
}
|
||||
|
||||
.variableName {
|
||||
font-family: 'Space Mono', monospace;
|
||||
color: var(--bg-robin-400);
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import { Check, X } from '@signozhq/icons';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { DialogWrapper } from '@signozhq/ui/dialog';
|
||||
|
||||
import styles from './ApplyToAllDialog.module.scss';
|
||||
|
||||
interface ApplyToAllDialogProps {
|
||||
open: boolean;
|
||||
variableName: string;
|
||||
isLoading: boolean;
|
||||
onConfirm: () => void;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
/** Confirms applying a dynamic variable as a filter to every panel. */
|
||||
function ApplyToAllDialog({
|
||||
open,
|
||||
variableName,
|
||||
isLoading,
|
||||
onConfirm,
|
||||
onClose,
|
||||
}: ApplyToAllDialogProps): JSX.Element {
|
||||
const footer = (
|
||||
<div className={styles.footer}>
|
||||
<Button variant="solid" color="secondary" onClick={onClose}>
|
||||
<X size={12} />
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="solid"
|
||||
color="primary"
|
||||
loading={isLoading}
|
||||
onClick={onConfirm}
|
||||
testId="confirm-apply-to-all"
|
||||
>
|
||||
<Check size={12} />
|
||||
Apply to all
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<DialogWrapper
|
||||
open={open}
|
||||
onOpenChange={(isOpen): void => {
|
||||
if (!isOpen) {
|
||||
onClose();
|
||||
}
|
||||
}}
|
||||
title="Apply variable to all panels"
|
||||
width="narrow"
|
||||
showCloseButton={false}
|
||||
// Lift above the settings drawer (z ~1000); overlay off (it would only half-dim).
|
||||
style={{ zIndex: 1100 }}
|
||||
showOverlay={false}
|
||||
footer={footer}
|
||||
>
|
||||
<div className={styles.body}>
|
||||
Add <span className={styles.variableName}>${variableName}</span> as a filter
|
||||
to every panel on this dashboard. Panels that already reference it are left
|
||||
unchanged.
|
||||
</div>
|
||||
</DialogWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default ApplyToAllDialog;
|
||||
@@ -64,7 +64,7 @@ $grid-columns: minmax(0, 2fr) minmax(0, 3fr);
|
||||
|
||||
.rowActions {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
top: 8px;
|
||||
right: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -22,8 +22,6 @@ interface VariableRowProps {
|
||||
onCancelDelete: () => void;
|
||||
/** Apply this variable's filter to all panels. Dynamic variables only. */
|
||||
onApplyToAll: (index: number) => void;
|
||||
/** True when this dynamic variable is already applied to every panel. */
|
||||
isAppliedToAll: boolean;
|
||||
}
|
||||
|
||||
/** A single draggable variable row in the two-column (name / description) table. */
|
||||
@@ -37,7 +35,6 @@ function VariableRow({
|
||||
onConfirmDelete,
|
||||
onCancelDelete,
|
||||
onApplyToAll,
|
||||
isAppliedToAll,
|
||||
}: VariableRowProps): JSX.Element {
|
||||
const {
|
||||
attributes,
|
||||
@@ -124,17 +121,12 @@ function VariableRow({
|
||||
{variable.type === 'DYNAMIC' ? (
|
||||
<TooltipSimple
|
||||
side="top"
|
||||
title={
|
||||
isAppliedToAll
|
||||
? 'Already applied to all panels'
|
||||
: 'Add this variable as a filter to every panel'
|
||||
}
|
||||
title="Add this variable as a filter to every panel"
|
||||
>
|
||||
<Button
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
size="sm"
|
||||
disabled={isAppliedToAll}
|
||||
className={styles.applyAllButton}
|
||||
onClick={(): void => onApplyToAll(index)}
|
||||
testId={`variable-apply-all-${variable.name}`}
|
||||
|
||||
@@ -26,8 +26,6 @@ interface VariablesListProps {
|
||||
onCancelDelete: () => void;
|
||||
onMove: (from: number, to: number) => void;
|
||||
onApplyToAll: (index: number) => void;
|
||||
/** Names of dynamic variables already applied to every panel. */
|
||||
appliedToAllNames: Set<string>;
|
||||
}
|
||||
|
||||
function VariablesList({
|
||||
@@ -40,7 +38,6 @@ function VariablesList({
|
||||
onCancelDelete,
|
||||
onMove,
|
||||
onApplyToAll,
|
||||
appliedToAllNames,
|
||||
}: VariablesListProps): JSX.Element {
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor, { activationConstraint: { distance: 1 } }),
|
||||
@@ -85,7 +82,6 @@ function VariablesList({
|
||||
onConfirmDelete={onConfirmDelete}
|
||||
onCancelDelete={onCancelDelete}
|
||||
onApplyToAll={onApplyToAll}
|
||||
isAppliedToAll={appliedToAllNames.has(variable.name)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,6 @@ import {
|
||||
type Dispatch,
|
||||
type SetStateAction,
|
||||
useCallback,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
@@ -14,6 +13,7 @@ import type {
|
||||
import { DashboardDetailEvents } from 'pages/DashboardPageV2/constants/events';
|
||||
|
||||
import { useDashboardStore } from '../../../store/useDashboardStore';
|
||||
import { buildSyncVariableToPanelsPatch } from '../utils/applyVariableToPanelsPatch';
|
||||
import {
|
||||
VARIABLE_TYPE_EVENT_LABEL,
|
||||
type VariableFormModel,
|
||||
@@ -23,9 +23,7 @@ import {
|
||||
buildVariableImpactPatch,
|
||||
} from '../utils/variableImpactPatch';
|
||||
import {
|
||||
findApplyUsages,
|
||||
findVariableUsages,
|
||||
isVariableAppliedToAllPanels,
|
||||
type VariableImpactMode,
|
||||
type VariableUsage,
|
||||
} from '../utils/variableUsages';
|
||||
@@ -42,8 +40,6 @@ export interface VariableImpact {
|
||||
newName?: string;
|
||||
usages: VariableUsage[];
|
||||
nextVariables: VariableFormModel[];
|
||||
/** Where an `apply` impact came from — drives the confirm analytics event. */
|
||||
origin?: 'form' | 'applyToAll';
|
||||
}
|
||||
|
||||
interface UseVariableListActionsParams {
|
||||
@@ -68,9 +64,6 @@ interface UseVariableListActions {
|
||||
handleMove: (from: number, to: number) => void;
|
||||
requestDelete: (index: number) => void;
|
||||
handleConfirmDelete: (index: number) => void;
|
||||
requestApplyToAll: (index: number) => void;
|
||||
/** Names of dynamic variables already applied to every panel (button disabled). */
|
||||
appliedToAllNames: Set<string>;
|
||||
handleImpactConfirm: (resolvedUsages: VariableUsage[]) => Promise<void>;
|
||||
}
|
||||
|
||||
@@ -114,52 +107,60 @@ export function useVariableListActions({
|
||||
next[editingIndex] = formModel;
|
||||
}
|
||||
|
||||
const isRename = !!oldName && oldName !== formModel.name;
|
||||
// Both rename and apply-to-panels edits are reviewed in the impact dialog
|
||||
// before persisting — never applied silently.
|
||||
const renameUsages = isRename
|
||||
? findVariableUsages(dashboard, oldName as string, 'rename', formModel.name)
|
||||
: [];
|
||||
const applyUsages =
|
||||
formModel.type === 'DYNAMIC' && formModel.dynamicAttribute
|
||||
? findApplyUsages(
|
||||
dashboard,
|
||||
formModel.dynamicAttribute,
|
||||
formModel.name,
|
||||
oldName ?? formModel.name,
|
||||
selectedPanelIds,
|
||||
)
|
||||
: [];
|
||||
|
||||
// Apply usages win per (panel, envelope) over a plain rename rewrite.
|
||||
const byId = new Map<string, VariableUsage>();
|
||||
renameUsages.forEach((usage) => byId.set(usage.id, usage));
|
||||
applyUsages.forEach((usage) => byId.set(usage.id, usage));
|
||||
const usages = [...byId.values()];
|
||||
|
||||
if (usages.length > 0) {
|
||||
setIsEditing(null);
|
||||
setImpact({
|
||||
mode: isRename ? 'rename' : 'apply',
|
||||
variableName: oldName ?? formModel.name,
|
||||
newName: formModel.name,
|
||||
usages,
|
||||
nextVariables: next,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// No cross-query impact — persist directly; keep the form open on failure.
|
||||
void (async (): Promise<void> => {
|
||||
const saved = await save(next);
|
||||
if (!saved) {
|
||||
// A rename that other queries/variables reference must be reviewed first, so
|
||||
// the references are rewritten alongside the rename (never left dangling).
|
||||
if (oldName && oldName !== formModel.name) {
|
||||
const usages = findVariableUsages(
|
||||
dashboard,
|
||||
oldName,
|
||||
'rename',
|
||||
formModel.name,
|
||||
);
|
||||
if (usages.length > 0) {
|
||||
setIsEditing(null);
|
||||
setImpact({
|
||||
mode: 'rename',
|
||||
variableName: oldName,
|
||||
newName: formModel.name,
|
||||
usages,
|
||||
nextVariables: next,
|
||||
});
|
||||
return;
|
||||
}
|
||||
setIsEditing(null);
|
||||
setVariables(next);
|
||||
}
|
||||
|
||||
setIsEditing(null);
|
||||
setVariables(next);
|
||||
void (async (): Promise<void> => {
|
||||
const saved = await save(next);
|
||||
if (!saved || formModel.type !== 'DYNAMIC') {
|
||||
return;
|
||||
}
|
||||
const ops = buildSyncVariableToPanelsPatch(
|
||||
dashboard.spec.panels,
|
||||
formModel.dynamicAttribute,
|
||||
formModel.name,
|
||||
selectedPanelIds,
|
||||
);
|
||||
if (ops.length === 0) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await patchAsync(ops);
|
||||
} catch {
|
||||
toast.error('Could not update panels');
|
||||
}
|
||||
})();
|
||||
},
|
||||
[dashboard, isEditing, save, setIsEditing, setVariables, variables],
|
||||
[
|
||||
dashboard,
|
||||
isEditing,
|
||||
patchAsync,
|
||||
save,
|
||||
setIsEditing,
|
||||
setVariables,
|
||||
variables,
|
||||
],
|
||||
);
|
||||
|
||||
const handleMove = useCallback(
|
||||
@@ -217,57 +218,6 @@ export function useVariableListActions({
|
||||
[dashboard, variables],
|
||||
);
|
||||
|
||||
// "Apply to all": review the additive changes across every panel before applying.
|
||||
const requestApplyToAll = useCallback(
|
||||
(index: number): void => {
|
||||
const variable = variables[index];
|
||||
if (!variable || variable.type !== 'DYNAMIC' || !variable.dynamicAttribute) {
|
||||
return;
|
||||
}
|
||||
const allPanelIds = Object.keys(dashboard.spec.panels ?? {});
|
||||
const usages = findApplyUsages(
|
||||
dashboard,
|
||||
variable.dynamicAttribute,
|
||||
variable.name,
|
||||
variable.name,
|
||||
allPanelIds,
|
||||
);
|
||||
if (usages.length === 0) {
|
||||
return;
|
||||
}
|
||||
setImpact({
|
||||
mode: 'apply',
|
||||
variableName: variable.name,
|
||||
newName: variable.name,
|
||||
usages,
|
||||
nextVariables: variables,
|
||||
origin: 'applyToAll',
|
||||
});
|
||||
},
|
||||
[dashboard, variables],
|
||||
);
|
||||
|
||||
// A dynamic variable is "applied to all" when every panel query already
|
||||
// references it — i.e. the apply review would be empty. Disables the button.
|
||||
const appliedToAllNames = useMemo(() => {
|
||||
const names = new Set<string>();
|
||||
variables.forEach((variable) => {
|
||||
if (variable.type !== 'DYNAMIC' || !variable.dynamicAttribute) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
isVariableAppliedToAllPanels(
|
||||
dashboard,
|
||||
variable.dynamicAttribute,
|
||||
variable.name,
|
||||
)
|
||||
) {
|
||||
names.add(variable.name);
|
||||
}
|
||||
});
|
||||
return names;
|
||||
}, [dashboard, variables]);
|
||||
|
||||
// Applies a resolved rename/delete: the variables array (rename/delete + edited
|
||||
// variable queries) and each touched panel's queries, in one atomic patch.
|
||||
const handleImpactConfirm = useCallback(
|
||||
@@ -287,15 +237,11 @@ export function useVariableListActions({
|
||||
setVariables(nextVariables);
|
||||
try {
|
||||
await patchAsync(ops);
|
||||
let message: string;
|
||||
if (impact.mode === 'rename') {
|
||||
message = `Renamed to $${impact.newName}`;
|
||||
} else if (impact.mode === 'apply') {
|
||||
message = `Applied $${impact.variableName} to panels`;
|
||||
} else {
|
||||
message = `Deleted $${impact.variableName}`;
|
||||
}
|
||||
toast.success(message);
|
||||
toast.success(
|
||||
impact.mode === 'rename'
|
||||
? `Renamed to $${impact.newName}`
|
||||
: `Deleted $${impact.variableName}`,
|
||||
);
|
||||
if (impact.mode === 'delete') {
|
||||
const deleted = variables.find((v) => v.name === impact.variableName);
|
||||
void logEvent(DashboardDetailEvents.VariableDeleted, {
|
||||
@@ -305,22 +251,13 @@ export function useVariableListActions({
|
||||
hadReferences: true,
|
||||
dashboardId,
|
||||
});
|
||||
} else if (impact.mode === 'apply' && impact.origin === 'applyToAll') {
|
||||
void logEvent(DashboardDetailEvents.ApplyToAllConfirmed, {
|
||||
variableType: 'dynamic',
|
||||
dashboardId,
|
||||
});
|
||||
}
|
||||
} catch {
|
||||
let message: string;
|
||||
if (impact.mode === 'rename') {
|
||||
message = 'Could not rename the variable';
|
||||
} else if (impact.mode === 'apply') {
|
||||
message = 'Could not apply the variable to panels';
|
||||
} else {
|
||||
message = 'Could not delete the variable';
|
||||
}
|
||||
toast.error(message);
|
||||
toast.error(
|
||||
impact.mode === 'rename'
|
||||
? 'Could not rename the variable'
|
||||
: 'Could not delete the variable',
|
||||
);
|
||||
}
|
||||
setImpact(null);
|
||||
},
|
||||
@@ -336,8 +273,6 @@ export function useVariableListActions({
|
||||
handleMove,
|
||||
requestDelete,
|
||||
handleConfirmDelete,
|
||||
requestApplyToAll,
|
||||
appliedToAllNames,
|
||||
handleImpactConfirm,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { toast } from '@signozhq/ui/sonner';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import type { DashboardtypesGettableDashboardV2DTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import cx from 'classnames';
|
||||
import { DashboardDetailEvents } from 'pages/DashboardPageV2/constants/events';
|
||||
|
||||
import settingsStyles from '../DashboardSettings.module.scss';
|
||||
import { useOptimisticPatch } from '../../hooks/useOptimisticPatch';
|
||||
import { useDashboardStore } from '../../store/useDashboardStore';
|
||||
import { getPanelIdsReferencingVariable } from './utils/applyVariableToPanelsPatch';
|
||||
import {
|
||||
buildApplyVariableToPanelsPatch,
|
||||
getPanelIdsReferencingVariable,
|
||||
} from './utils/applyVariableToPanelsPatch';
|
||||
import { useSaveVariables } from './hooks/useSaveVariables';
|
||||
import { useVariableListActions } from './hooks/useVariableListActions';
|
||||
import { dtoToFormModel } from './variableAdapters';
|
||||
@@ -18,6 +24,7 @@ import VariableImpactDialog from './VariableImpactDialog/VariableImpactDialog';
|
||||
import VariablesList from './components/VariablesList/VariablesList';
|
||||
import styles from './Variables.module.scss';
|
||||
import AddVariableButton from './components/AddVariableButton';
|
||||
import ApplyToAllDialog from './components/ApplyToAllDialog/ApplyToAllDialog';
|
||||
import NoVariablesCard from './components/NoVariablesCard/NoVariablesCard';
|
||||
import { EditingState } from './types';
|
||||
|
||||
@@ -27,6 +34,7 @@ interface VariablesSettingsProps {
|
||||
|
||||
function VariablesSettings({ dashboard }: VariablesSettingsProps): JSX.Element {
|
||||
const isEditable = useDashboardStore((s) => s.isEditable);
|
||||
const dashboardId = useDashboardStore((s) => s.dashboardId);
|
||||
// The drawer destroys on close, so reading this once on mount is enough to
|
||||
// open the add-form when deep-linked (e.g. the bar's "Add variable" button).
|
||||
const openAddOnMount = useDashboardStore(
|
||||
@@ -51,6 +59,7 @@ function VariablesSettings({ dashboard }: VariablesSettingsProps): JSX.Element {
|
||||
const [isEditing, setIsEditing] = useState<EditingState>(
|
||||
openAddOnMount && isEditable ? { type: 'new' } : null,
|
||||
);
|
||||
const [applyToAllIndex, setApplyToAllIndex] = useState<number | null>(null);
|
||||
|
||||
const {
|
||||
confirmDeleteIndex,
|
||||
@@ -61,8 +70,6 @@ function VariablesSettings({ dashboard }: VariablesSettingsProps): JSX.Element {
|
||||
handleMove,
|
||||
requestDelete,
|
||||
handleConfirmDelete,
|
||||
requestApplyToAll,
|
||||
appliedToAllNames,
|
||||
handleImpactConfirm,
|
||||
} = useVariableListActions({
|
||||
dashboard,
|
||||
@@ -109,6 +116,36 @@ function VariablesSettings({ dashboard }: VariablesSettingsProps): JSX.Element {
|
||||
);
|
||||
}, [editingFormModel, dashboard.spec.panels]);
|
||||
|
||||
const applyToAllVariable =
|
||||
applyToAllIndex === null ? null : variables[applyToAllIndex];
|
||||
|
||||
const handleConfirmApplyToAll = async (): Promise<void> => {
|
||||
if (!applyToAllVariable) {
|
||||
return;
|
||||
}
|
||||
const ops = buildApplyVariableToPanelsPatch(
|
||||
dashboard.spec.panels,
|
||||
applyToAllVariable.dynamicAttribute,
|
||||
applyToAllVariable.name,
|
||||
);
|
||||
if (ops.length === 0) {
|
||||
toast.info('No panels needed this filter.');
|
||||
setApplyToAllIndex(null);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await patchAsync(ops);
|
||||
toast.success(`Applied $${applyToAllVariable.name} to all panels`);
|
||||
void logEvent(DashboardDetailEvents.ApplyToAllConfirmed, {
|
||||
variableType: 'dynamic',
|
||||
dashboardId,
|
||||
});
|
||||
} catch {
|
||||
toast.error('Could not apply the variable to panels');
|
||||
}
|
||||
setApplyToAllIndex(null);
|
||||
};
|
||||
|
||||
if (editingFormModel) {
|
||||
return (
|
||||
<VariableForm
|
||||
@@ -139,14 +176,20 @@ function VariablesSettings({ dashboard }: VariablesSettingsProps): JSX.Element {
|
||||
onConfirmDelete={handleConfirmDelete}
|
||||
onCancelDelete={(): void => setConfirmDeleteIndex(null)}
|
||||
onMove={handleMove}
|
||||
onApplyToAll={requestApplyToAll}
|
||||
appliedToAllNames={appliedToAllNames}
|
||||
onApplyToAll={(index): void => setApplyToAllIndex(index)}
|
||||
/>
|
||||
<div className={styles.footer}>
|
||||
<AddVariableButton isEditable={isEditable} setIsEditing={setIsEditing} />
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<ApplyToAllDialog
|
||||
open={applyToAllVariable !== null}
|
||||
variableName={applyToAllVariable?.name ?? ''}
|
||||
isLoading={isPatching}
|
||||
onConfirm={(): void => void handleConfirmApplyToAll()}
|
||||
onClose={(): void => setApplyToAllIndex(null)}
|
||||
/>
|
||||
<VariableImpactDialog
|
||||
open={impact !== null}
|
||||
mode={impact?.mode ?? 'delete'}
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
import type {
|
||||
DashboardtypesDashboardSpecDTOPanels,
|
||||
DashboardtypesJSONPatchOperationDTO,
|
||||
DashboardtypesQueryDTO,
|
||||
Querybuildertypesv5BuilderQuerySpecDTO,
|
||||
Querybuildertypesv5CompositeQueryDTO,
|
||||
Querybuildertypesv5QueryEnvelopeBuilderDTO,
|
||||
} from 'api/generated/services/sigNoz.schemas';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
// Injects/removes a dynamic variable's filter (`attribute IN $name`) in panel
|
||||
// builder queries as JSON-Patch ops. Only builder queries carry a filter.
|
||||
|
||||
function clauseFor(attribute: string, variableName: string): string {
|
||||
return `${attribute} IN $${variableName}`;
|
||||
}
|
||||
|
||||
/** Runs `fn` on every builder-query spec in a panel's single query (Composite or bare Builder). */
|
||||
function forEachBuilderSpec(
|
||||
queries: DashboardtypesQueryDTO[],
|
||||
fn: (spec: Querybuildertypesv5BuilderQuerySpecDTO) => void,
|
||||
@@ -33,6 +39,48 @@ function forEachBuilderSpec(
|
||||
}
|
||||
}
|
||||
|
||||
/** Appends the clause to every builder query's filter. Returns whether anything changed. */
|
||||
function addClause(queries: DashboardtypesQueryDTO[], clause: string): boolean {
|
||||
let changed = false;
|
||||
forEachBuilderSpec(queries, (spec) => {
|
||||
const existing = spec.filter?.expression?.trim();
|
||||
// Idempotent: a repeated apply must not stack duplicate clauses.
|
||||
if (existing?.includes(clause)) {
|
||||
return;
|
||||
}
|
||||
spec.filter = {
|
||||
expression: existing ? `${existing} AND ${clause}` : clause,
|
||||
};
|
||||
changed = true;
|
||||
});
|
||||
return changed;
|
||||
}
|
||||
|
||||
/** Removes the managed clause (an ` AND `-joined part) from every builder filter. */
|
||||
function removeClause(
|
||||
queries: DashboardtypesQueryDTO[],
|
||||
clause: string,
|
||||
): boolean {
|
||||
let changed = false;
|
||||
forEachBuilderSpec(queries, (spec) => {
|
||||
const existing = spec.filter?.expression;
|
||||
if (!existing) {
|
||||
return;
|
||||
}
|
||||
const parts = existing
|
||||
.split(' AND ')
|
||||
.map((part) => part.trim())
|
||||
.filter(Boolean);
|
||||
const kept = parts.filter((part) => part !== clause);
|
||||
if (kept.length !== parts.length) {
|
||||
spec.filter = { expression: kept.join(' AND ') };
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
return changed;
|
||||
}
|
||||
|
||||
/** Whether any builder query in the panel already carries the clause. */
|
||||
function panelHasClause(
|
||||
queries: DashboardtypesQueryDTO[],
|
||||
clause: string,
|
||||
@@ -46,6 +94,74 @@ function panelHasClause(
|
||||
return has;
|
||||
}
|
||||
|
||||
function replaceQueriesOp(
|
||||
panelId: string,
|
||||
queries: DashboardtypesQueryDTO[],
|
||||
): DashboardtypesJSONPatchOperationDTO {
|
||||
return {
|
||||
op: 'replace' as DashboardtypesJSONPatchOperationDTO['op'],
|
||||
path: `/spec/panels/${panelId}/spec/queries`,
|
||||
value: queries,
|
||||
};
|
||||
}
|
||||
|
||||
/** Add-only: inject the variable's filter into the given panels (default: all). */
|
||||
export function buildApplyVariableToPanelsPatch(
|
||||
panels: DashboardtypesDashboardSpecDTOPanels,
|
||||
attribute: string,
|
||||
variableName: string,
|
||||
targetPanelIds?: string[],
|
||||
): DashboardtypesJSONPatchOperationDTO[] {
|
||||
if (!attribute || !variableName) {
|
||||
return [];
|
||||
}
|
||||
const clause = clauseFor(attribute, variableName);
|
||||
const ids = targetPanelIds ?? Object.keys(panels);
|
||||
|
||||
const ops: DashboardtypesJSONPatchOperationDTO[] = [];
|
||||
ids.forEach((id) => {
|
||||
const panel = panels[id];
|
||||
if (!panel?.spec?.queries?.length) {
|
||||
return;
|
||||
}
|
||||
const queries = cloneDeep(panel.spec.queries);
|
||||
if (addClause(queries, clause)) {
|
||||
ops.push(replaceQueriesOp(id, queries));
|
||||
}
|
||||
});
|
||||
return ops;
|
||||
}
|
||||
|
||||
/** Full sync: selected panels get the clause; every other panel has it removed. */
|
||||
export function buildSyncVariableToPanelsPatch(
|
||||
panels: DashboardtypesDashboardSpecDTOPanels,
|
||||
attribute: string,
|
||||
variableName: string,
|
||||
selectedPanelIds: string[],
|
||||
): DashboardtypesJSONPatchOperationDTO[] {
|
||||
if (!attribute || !variableName) {
|
||||
return [];
|
||||
}
|
||||
const clause = clauseFor(attribute, variableName);
|
||||
const selected = new Set(selectedPanelIds);
|
||||
|
||||
const ops: DashboardtypesJSONPatchOperationDTO[] = [];
|
||||
Object.keys(panels).forEach((id) => {
|
||||
const panel = panels[id];
|
||||
if (!panel?.spec?.queries?.length) {
|
||||
return;
|
||||
}
|
||||
const queries = cloneDeep(panel.spec.queries);
|
||||
const changed = selected.has(id)
|
||||
? addClause(queries, clause)
|
||||
: removeClause(queries, clause);
|
||||
if (changed) {
|
||||
ops.push(replaceQueriesOp(id, queries));
|
||||
}
|
||||
});
|
||||
return ops;
|
||||
}
|
||||
|
||||
/** Panel ids whose queries currently reference the variable — pre-populates the picker. */
|
||||
export function getPanelIdsReferencingVariable(
|
||||
panels: DashboardtypesDashboardSpecDTOPanels,
|
||||
|
||||
@@ -2,10 +2,7 @@ import type {
|
||||
DashboardtypesGettableDashboardV2DTO,
|
||||
Querybuildertypesv5QueryEnvelopeDTO,
|
||||
} from 'api/generated/services/sigNoz.schemas';
|
||||
import {
|
||||
appendAndClause,
|
||||
removeVariableFromExpression,
|
||||
} from 'components/QueryBuilderV2/utils';
|
||||
import { removeVariableFromExpression } from 'components/QueryBuilderV2/utils';
|
||||
import {
|
||||
rewriteVariableReferences,
|
||||
textContainsVariableReference,
|
||||
@@ -21,7 +18,8 @@ export type VariableUsageKind =
|
||||
| 'clickhouse'
|
||||
| 'variable';
|
||||
|
||||
export type VariableImpactMode = 'rename' | 'delete' | 'apply';
|
||||
/** Whether the impact is a rename (rewrite refs) or a delete (remove refs). */
|
||||
export type VariableImpactMode = 'rename' | 'delete';
|
||||
|
||||
/**
|
||||
* One place a variable is referenced — a panel query's builder filter expression,
|
||||
@@ -163,118 +161,3 @@ export function findVariableUsages(
|
||||
|
||||
return usages;
|
||||
}
|
||||
|
||||
// `matchName` is the name in the current query text (the old name during a
|
||||
// simultaneous rename); `injectName` is written into newly added clauses. Equal
|
||||
// outside of a rename.
|
||||
export function findApplyUsages(
|
||||
dashboard: DashboardtypesGettableDashboardV2DTO,
|
||||
attribute: string,
|
||||
injectName: string,
|
||||
matchName: string,
|
||||
selectedPanelIds: string[],
|
||||
): VariableUsage[] {
|
||||
if (!attribute || !injectName) {
|
||||
return [];
|
||||
}
|
||||
const clause = `${attribute} IN $${injectName}`;
|
||||
const existingClause = `${attribute} IN $${matchName}`;
|
||||
const selected = new Set(selectedPanelIds);
|
||||
const usages: VariableUsage[] = [];
|
||||
|
||||
Object.entries(dashboard.spec.panels ?? {}).forEach(([panelId, panel]) => {
|
||||
const queries = panel?.spec?.queries;
|
||||
if (!queries?.length) {
|
||||
return;
|
||||
}
|
||||
toQueryEnvelopes(queries).forEach((envelope, index) => {
|
||||
const pushUsage = (
|
||||
kind: VariableUsageKind,
|
||||
currentText: string,
|
||||
resultingText: string,
|
||||
): void => {
|
||||
usages.push({
|
||||
id: `panel:${panelId}:${index}`,
|
||||
sourceType: 'panel',
|
||||
sourceId: panelId,
|
||||
sourceLabel: panel.spec?.display?.name || panelId,
|
||||
kind,
|
||||
envelopeIndex: index,
|
||||
currentText,
|
||||
resultingText,
|
||||
});
|
||||
};
|
||||
|
||||
if (envelope.type === 'builder_query') {
|
||||
const spec = envelope.spec as
|
||||
| { filter?: { expression?: string } }
|
||||
| undefined;
|
||||
const current = spec?.filter?.expression ?? '';
|
||||
if (selected.has(panelId)) {
|
||||
// Already carries the clause (under either name) — a rename usage, if
|
||||
// any, fixes the name; don't append a duplicate.
|
||||
if (current.includes(clause) || current.includes(existingClause)) {
|
||||
return;
|
||||
}
|
||||
pushUsage('builder', current, appendAndClause(current, clause));
|
||||
} else {
|
||||
const next = removeVariableFromExpression(current, matchName);
|
||||
if (next !== current) {
|
||||
pushUsage('builder', current, next);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// PromQL/ClickHouse can't carry the managed clause — never auto-inject or
|
||||
// remove. Selected panels still get an editable row defaulting to the
|
||||
// current text, unless the query already references the variable.
|
||||
if (!selected.has(panelId)) {
|
||||
return;
|
||||
}
|
||||
const ref = envelopeReferenceText(envelope);
|
||||
if (!ref) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
textContainsVariableReference(ref.text, injectName) ||
|
||||
textContainsVariableReference(ref.text, matchName)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
pushUsage(ref.kind, ref.text, ref.text);
|
||||
});
|
||||
});
|
||||
|
||||
return usages;
|
||||
}
|
||||
|
||||
// Cheap yes/no check for the "Apply to all" disabled state: does every panel query
|
||||
// already reference the variable? Plain string checks — no ANTLR, no rewriting.
|
||||
export function isVariableAppliedToAllPanels(
|
||||
dashboard: DashboardtypesGettableDashboardV2DTO,
|
||||
attribute: string,
|
||||
variableName: string,
|
||||
): boolean {
|
||||
if (!attribute || !variableName) {
|
||||
return false;
|
||||
}
|
||||
const clause = `${attribute} IN $${variableName}`;
|
||||
const panels = dashboard.spec.panels ?? {};
|
||||
return Object.values(panels).every((panel) => {
|
||||
const queries = panel?.spec?.queries;
|
||||
if (!queries?.length) {
|
||||
return true;
|
||||
}
|
||||
return toQueryEnvelopes(queries).every((envelope) => {
|
||||
if (envelope.type === 'builder_query') {
|
||||
const spec = envelope.spec as
|
||||
| { filter?: { expression?: string } }
|
||||
| undefined;
|
||||
return (spec?.filter?.expression ?? '').includes(clause);
|
||||
}
|
||||
const ref = envelopeReferenceText(envelope);
|
||||
return ref ? textContainsVariableReference(ref.text, variableName) : true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -13,7 +13,11 @@ 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';
|
||||
@@ -65,8 +69,12 @@ export function dtoToFormModel(
|
||||
...listCommon,
|
||||
type: 'DYNAMIC',
|
||||
dynamicAttribute: plugin.spec.name ?? '',
|
||||
// signal is a required wire field (`all` = every telemetry signal), used as-is.
|
||||
dynamicSignal: plugin.spec.signal,
|
||||
// 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,
|
||||
};
|
||||
}
|
||||
// Default to Query (also covers a query plugin or a missing/unknown plugin).
|
||||
@@ -94,7 +102,7 @@ function buildPlugin(
|
||||
kind: DynamicPluginKind['signoz/DynamicVariable'],
|
||||
spec: {
|
||||
name: model.dynamicAttribute,
|
||||
signal: model.dynamicSignal,
|
||||
signal: signalForApi(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,6 +23,23 @@ 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
|
||||
@@ -64,38 +81,25 @@ export const VARIABLE_SORT_LABEL: Record<VariableSort, string> = {
|
||||
[VARIABLE_SORT.CI_DESC]: 'Alphabetical, case-insensitive (descending)',
|
||||
};
|
||||
|
||||
export const DYNAMIC_SIGNALS: DashboardtypesDynamicVariableSignalDTO[] = [
|
||||
DashboardtypesDynamicVariableSignalDTO.all,
|
||||
DashboardtypesDynamicVariableSignalDTO.traces,
|
||||
DashboardtypesDynamicVariableSignalDTO.logs,
|
||||
DashboardtypesDynamicVariableSignalDTO.metrics,
|
||||
export const DYNAMIC_SIGNALS: DynamicSignalOption[] = [
|
||||
DYNAMIC_SIGNAL_ALL,
|
||||
TelemetrytypesSignalDTO.traces,
|
||||
TelemetrytypesSignalDTO.logs,
|
||||
TelemetrytypesSignalDTO.metrics,
|
||||
];
|
||||
|
||||
export const DYNAMIC_SIGNAL_LABEL: Record<
|
||||
DashboardtypesDynamicVariableSignalDTO,
|
||||
string
|
||||
> = {
|
||||
[DashboardtypesDynamicVariableSignalDTO.all]: 'All telemetry',
|
||||
[DashboardtypesDynamicVariableSignalDTO.traces]: 'Traces',
|
||||
[DashboardtypesDynamicVariableSignalDTO.logs]: 'Logs',
|
||||
[DashboardtypesDynamicVariableSignalDTO.metrics]: 'Metrics',
|
||||
export const DYNAMIC_SIGNAL_LABEL: Record<DynamicSignalOption, string> = {
|
||||
[DYNAMIC_SIGNAL_ALL]: 'All telemetry',
|
||||
[TelemetrytypesSignalDTO.traces]: 'Traces',
|
||||
[TelemetrytypesSignalDTO.logs]: 'Logs',
|
||||
[TelemetrytypesSignalDTO.metrics]: 'Metrics',
|
||||
};
|
||||
|
||||
/**
|
||||
* Field-keys/values API param. The `all` signal is omitted (that endpoint only
|
||||
* accepts a concrete signal), everything else passes through.
|
||||
*/
|
||||
/** Maps the editor's signal selection to the wire value (`'all'` → omitted). */
|
||||
export function signalForApi(
|
||||
signal: DashboardtypesDynamicVariableSignalDTO,
|
||||
):
|
||||
| Exclude<
|
||||
DashboardtypesDynamicVariableSignalDTO,
|
||||
DashboardtypesDynamicVariableSignalDTO.all
|
||||
>
|
||||
| undefined {
|
||||
return signal === DashboardtypesDynamicVariableSignalDTO.all
|
||||
? undefined
|
||||
: signal;
|
||||
signal: DynamicSignalOption,
|
||||
): TelemetrySignal | undefined {
|
||||
return signal === DYNAMIC_SIGNAL_ALL ? undefined : signal;
|
||||
}
|
||||
|
||||
type SortableValues = (string | number | boolean)[];
|
||||
@@ -140,7 +144,7 @@ export interface VariableFormModel {
|
||||
textValue: string; // TEXT
|
||||
textConstant: boolean; // TEXT
|
||||
dynamicAttribute: string; // DYNAMIC — the telemetry field name
|
||||
dynamicSignal: DashboardtypesDynamicVariableSignalDTO; // DYNAMIC — the telemetry signal (`all` = every signal)
|
||||
dynamicSignal: DynamicSignalOption; // DYNAMIC — the telemetry signal
|
||||
|
||||
/**
|
||||
* Runtime-selected default, not editable in the management tab yet; carried
|
||||
@@ -162,6 +166,6 @@ export function emptyVariableFormModel(): VariableFormModel {
|
||||
textValue: '',
|
||||
textConstant: false,
|
||||
dynamicAttribute: '',
|
||||
dynamicSignal: DashboardtypesDynamicVariableSignalDTO.all,
|
||||
dynamicSignal: DYNAMIC_SIGNAL_ALL,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ 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[] => spec.links || [],
|
||||
get: (spec): DashboardtypesLinkDTO[] | undefined => spec.links ?? undefined,
|
||||
update: (spec, links): PanelSpec => ({ ...spec, links }),
|
||||
},
|
||||
// One editor for every threshold variant (label / comparison / table); the kind's
|
||||
|
||||
@@ -49,14 +49,6 @@ 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'],
|
||||
@@ -75,34 +67,16 @@ describe('newPanelRoute', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('carries the query as a compositeQuery param the reader can decode', () => {
|
||||
it('carries the query as a decodable compositeQuery param', () => {
|
||||
const link = buildExportPanelLink({
|
||||
dashboardId: 'dash-1',
|
||||
panelType: PANEL_TYPES.TIME_SERIES,
|
||||
query,
|
||||
});
|
||||
const { params } = parseLink(link);
|
||||
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);
|
||||
expect(JSON.parse(params.get('compositeQuery') as string)).toStrictEqual(
|
||||
query,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns null for a panel type with no V2 kind', () => {
|
||||
|
||||
@@ -45,11 +45,9 @@ export function parseNewPanelKind(
|
||||
|
||||
/**
|
||||
* New-panel editor link that exports an explorer query into a V2 dashboard. Carries the
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
export function buildExportPanelLink({
|
||||
dashboardId,
|
||||
@@ -70,7 +68,7 @@ export function buildExportPanelLink({
|
||||
});
|
||||
return `${path}${newPanelSearch(kind)}&${
|
||||
QueryParams.compositeQuery
|
||||
}=${encodeURIComponent(encodeURIComponent(JSON.stringify(query)))}`;
|
||||
}=${encodeURIComponent(JSON.stringify(query))}`;
|
||||
}
|
||||
|
||||
/** Target section index for a new panel, or undefined when unset/invalid. */
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
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);
|
||||
});
|
||||
});
|
||||
@@ -1,8 +0,0 @@
|
||||
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,4 @@
|
||||
import type { DashboardtypesPanelSpecDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import type { DashboardtypesLinkDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import { resolveTexts } from 'hooks/dashboard/useContextVariables';
|
||||
|
||||
import { resolveContextLinkUrl } from './resolveContextLinkUrl';
|
||||
@@ -15,7 +15,7 @@ export interface ResolvedDrilldownLink {
|
||||
* label + URL, drops links without a URL, and skips substitution when `renderVariables === false`.
|
||||
*/
|
||||
export function resolvePanelContextLinks(
|
||||
links: DashboardtypesPanelSpecDTO['links'],
|
||||
links: DashboardtypesLinkDTO[] | undefined,
|
||||
processedVariables: Record<string, string>,
|
||||
): ResolvedDrilldownLink[] {
|
||||
const usable = (links ?? []).filter((link) => !!link.url);
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import {
|
||||
DashboardtypesDynamicVariableSignalDTO,
|
||||
TelemetrytypesSignalDTO,
|
||||
} from 'api/generated/services/sigNoz.schemas';
|
||||
import { TelemetrytypesSignalDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import type { BuilderQuery } from 'types/api/v5/queryRange';
|
||||
|
||||
/**
|
||||
@@ -20,23 +17,3 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
ScrollText,
|
||||
} from '@signozhq/icons';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import type { DashboardtypesPanelSpecDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import type { DashboardtypesLinkDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import { getAggregateColumnHeader } from 'container/QueryTable/Drilldown/drilldownUtils';
|
||||
import ContextMenu from 'periscope/components/ContextMenu';
|
||||
import type { DrilldownContext } from 'pages/DashboardPageV2/DashboardContainer/Panels/types/drilldown';
|
||||
@@ -29,7 +29,7 @@ interface DrilldownAggregateMenuProps {
|
||||
/** While dashboard variables resolve, the actions show a spinner and are disabled. */
|
||||
isResolving?: boolean;
|
||||
/** Panel's context links; resolved against the clicked point + variables here. */
|
||||
links: DashboardtypesPanelSpecDTO['links'];
|
||||
links: DashboardtypesLinkDTO[] | undefined;
|
||||
/** Whether the clicked point exposes group-by fields to bind to dashboard variables. */
|
||||
canSetDashboardVariables: boolean;
|
||||
onViewLogs: () => void;
|
||||
|
||||
@@ -15,7 +15,6 @@ import PanelHeaderSearch from './PanelHeaderSearch';
|
||||
import PanelStatusPopover from '../PanelStatus/PanelStatusPopover';
|
||||
import {
|
||||
panelStatusFromError,
|
||||
panelStatusFromMultipleEnabledQueries,
|
||||
panelStatusFromWarning,
|
||||
} from '../PanelStatus/utils';
|
||||
import styles from './PanelHeader.module.scss';
|
||||
@@ -75,24 +74,11 @@ 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 &&
|
||||
!multiQueryWarningDetail &&
|
||||
hideActions
|
||||
) {
|
||||
if (!name && !description && !errorDetail && !warningDetail && hideActions) {
|
||||
return <Fragment />;
|
||||
}
|
||||
|
||||
@@ -138,13 +124,6 @@ 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,8 +17,6 @@ const VARIANT_CONFIG: Record<
|
||||
interface PanelStatusPopoverProps {
|
||||
variant: PanelStatusVariant;
|
||||
detail: PanelStatusDetail;
|
||||
/** Overrides the trigger's test id; defaults to `panel-status-<variant>`. */
|
||||
testId?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,7 +26,6 @@ interface PanelStatusPopoverProps {
|
||||
function PanelStatusPopover({
|
||||
variant,
|
||||
detail,
|
||||
testId,
|
||||
}: PanelStatusPopoverProps): JSX.Element {
|
||||
const { color, ariaLabel } = VARIANT_CONFIG[variant];
|
||||
const Icon = variant === 'error' ? CircleX : TriangleAlert;
|
||||
@@ -44,7 +41,7 @@ function PanelStatusPopover({
|
||||
<span
|
||||
className={styles.trigger}
|
||||
aria-label={ariaLabel}
|
||||
data-testid={testId ?? `panel-status-${variant}`}
|
||||
data-testid={`panel-status-${variant}`}
|
||||
>
|
||||
<Icon size={16} color={color} />
|
||||
</span>
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
import type {
|
||||
DashboardtypesPanelDTO,
|
||||
Querybuildertypesv5QueryWarnDataDTO as WarningDTO,
|
||||
RenderErrorResponseDTO,
|
||||
} from 'api/generated/services/sigNoz.schemas';
|
||||
import type { 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,
|
||||
panelStatusFromMultipleEnabledQueries,
|
||||
panelStatusFromWarning,
|
||||
} from '../utils';
|
||||
import { panelStatusFromError, 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.
|
||||
@@ -94,62 +87,3 @@ 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,11 +1,7 @@
|
||||
import { convertToApiError } from 'api/ErrorResponseHandlerForGeneratedAPIs';
|
||||
import type {
|
||||
DashboardtypesPanelDTO,
|
||||
Querybuildertypesv5QueryWarnDataDTO as WarningDTO,
|
||||
RenderErrorResponseDTO,
|
||||
} from 'api/generated/services/sigNoz.schemas';
|
||||
import type { RenderErrorResponseDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import type { AxiosError } from 'axios';
|
||||
import { countEnabledQueries } from 'pages/DashboardPageV2/DashboardContainer/Panels/utils/countEnabledQueries';
|
||||
import type { Querybuildertypesv5QueryWarnDataDTO as WarningDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
|
||||
import type { PanelStatusDetail } from './types';
|
||||
|
||||
@@ -56,25 +52,3 @@ 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,40 +41,6 @@ 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',
|
||||
@@ -135,53 +101,6 @@ 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 { DashboardtypesDynamicVariableSignalDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import { TelemetrytypesSignalDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import type { FilterData } from 'container/QueryTable/Drilldown/drilldownUtils';
|
||||
|
||||
import DrilldownDashboardVariablesMenu from '../DrilldownMenu/DrilldownDashboardVariablesMenu';
|
||||
@@ -63,6 +63,7 @@ jest.mock(
|
||||
'pages/DashboardPageV2/DashboardContainer/DashboardSettings/Variables/variableFormModel',
|
||||
() => ({
|
||||
emptyVariableFormModel: (): unknown => ({}),
|
||||
DYNAMIC_SIGNAL_ALL: 'all',
|
||||
}),
|
||||
);
|
||||
jest.mock('components/OverlayScrollbar/OverlayScrollbar', () => ({
|
||||
@@ -83,7 +84,7 @@ function renderItems(): void {
|
||||
const { result } = renderHook(() =>
|
||||
useDrilldownDashboardVariables({
|
||||
filters,
|
||||
signal: DashboardtypesDynamicVariableSignalDTO.metrics,
|
||||
signal: TelemetrytypesSignalDTO.metrics,
|
||||
onClose: jest.fn(),
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -19,7 +19,6 @@ 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';
|
||||
|
||||
@@ -164,7 +163,7 @@ export function useDrilldown(
|
||||
|
||||
const dashboardVariables = useDrilldownDashboardVariables({
|
||||
filters: context?.filters ?? EMPTY_FILTERS,
|
||||
signal: dynamicSignalFromQuerySignal(context?.signal),
|
||||
signal: context?.signal,
|
||||
onClose: handleClose,
|
||||
});
|
||||
|
||||
@@ -222,7 +221,7 @@ export function useDrilldown(
|
||||
context={context}
|
||||
query={v1Query}
|
||||
isResolving={isResolving}
|
||||
links={panel.spec.links}
|
||||
links={panel.spec.links ?? undefined}
|
||||
canSetDashboardVariables={dashboardVariables.hasFieldVariables}
|
||||
onViewLogs={(): void => navigate('view_logs')}
|
||||
onViewTraces={(): void => navigate('view_traces')}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { toast } from '@signozhq/ui/sonner';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { DashboardtypesDynamicVariableSignalDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
import type { TelemetrytypesSignalDTO } 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';
|
||||
@@ -22,8 +23,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[];
|
||||
/** Dynamic-variable signal derived from the clicked query — seeds a created variable's `dynamicSignal`. */
|
||||
signal?: DashboardtypesDynamicVariableSignalDTO;
|
||||
/** Clicked query's telemetry signal — seeds a created variable's `dynamicSignal`. */
|
||||
signal?: TelemetrytypesSignalDTO;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
@@ -110,7 +111,8 @@ export function useDrilldownDashboardVariables({
|
||||
type: 'DYNAMIC',
|
||||
multiSelect: true,
|
||||
dynamicAttribute: fieldName,
|
||||
dynamicSignal: signal ?? DashboardtypesDynamicVariableSignalDTO.all,
|
||||
// `||` (not `??`): an empty "any" signal maps to All, same as unset.
|
||||
dynamicSignal: signal || DYNAMIC_SIGNAL_ALL,
|
||||
};
|
||||
try {
|
||||
await patchAsync(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.body {
|
||||
flex: 1;
|
||||
padding: 12px 16px;
|
||||
padding: 12px 24px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
.footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { DialogWrapper } from '@signozhq/ui/dialog';
|
||||
import { Modal } from 'antd';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
|
||||
import { DASHBOARD_NAME_MAX_LENGTH } from '../../constants';
|
||||
import styles from './SectionTitleModal.module.scss';
|
||||
|
||||
interface SectionTitleModalProps {
|
||||
open: boolean;
|
||||
@@ -19,7 +17,7 @@ interface SectionTitleModalProps {
|
||||
onSubmit: (title: string) => void;
|
||||
}
|
||||
|
||||
/** Title-entry modal shared by section create and rename (mirrors RenameDashboardModal). */
|
||||
/** Title-entry modal shared by section create and rename. */
|
||||
function SectionTitleModal({
|
||||
open,
|
||||
heading,
|
||||
@@ -39,51 +37,22 @@ function SectionTitleModal({
|
||||
}
|
||||
}, [open, initialValue]);
|
||||
|
||||
// `!isSaving` also guards a second submit (e.g. a double Enter) while a request
|
||||
// is in flight — otherwise two sections would be created.
|
||||
const canSave = value.trim().length > 0 && !isSaving;
|
||||
|
||||
const submit = (): void => {
|
||||
if (!canSave) {
|
||||
return;
|
||||
const trimmed = value.trim();
|
||||
if (trimmed) {
|
||||
onSubmit(trimmed);
|
||||
}
|
||||
onSubmit(value.trim());
|
||||
};
|
||||
|
||||
return (
|
||||
<DialogWrapper
|
||||
title={heading}
|
||||
<Modal
|
||||
open={open}
|
||||
width="narrow"
|
||||
onOpenChange={(next): void => {
|
||||
if (!next) {
|
||||
onClose();
|
||||
}
|
||||
}}
|
||||
footer={
|
||||
<div className={styles.footer}>
|
||||
<Button
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
size="md"
|
||||
onClick={onClose}
|
||||
testId="section-title-cancel"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="solid"
|
||||
color="primary"
|
||||
size="md"
|
||||
disabled={!canSave}
|
||||
loading={isSaving}
|
||||
onClick={submit}
|
||||
testId="section-title-submit"
|
||||
>
|
||||
{okText}
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
title={heading}
|
||||
onCancel={onClose}
|
||||
onOk={submit}
|
||||
okText={okText}
|
||||
okButtonProps={{ disabled: isSaving || !value.trim() }}
|
||||
destroyOnClose
|
||||
>
|
||||
<Input
|
||||
testId="section-title-input"
|
||||
@@ -93,13 +62,13 @@ function SectionTitleModal({
|
||||
placeholder={placeholder}
|
||||
onChange={(e): void => setValue(e.target.value)}
|
||||
onKeyDown={(e): void => {
|
||||
if (e.key === 'Enter' && canSave) {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
submit();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</DialogWrapper>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ interface Params {
|
||||
}
|
||||
|
||||
interface Result {
|
||||
addSection: (title: string) => Promise<boolean>;
|
||||
addSection: (title: string) => Promise<void>;
|
||||
isSaving: boolean;
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@ export function useAddSection({ layouts }: Params): Result {
|
||||
const setScrollTargetId = useScrollIntoViewStore((s) => s.setScrollTargetId);
|
||||
|
||||
const addSection = useCallback(
|
||||
async (title: string): Promise<boolean> => {
|
||||
async (title: string): Promise<void> => {
|
||||
const trimmed = title.trim();
|
||||
if (!dashboardId || !trimmed) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
const isFirstSection = !layouts || layouts.length === 0;
|
||||
const op = isFirstSection
|
||||
@@ -58,10 +58,8 @@ export function useAddSection({ layouts }: Params): Result {
|
||||
// key it the way `getSectionStableId` does so it reveals itself on render.
|
||||
const newIndex = isFirstSection ? 0 : layouts.length;
|
||||
setScrollTargetId(getSectionStableId([], newIndex));
|
||||
return true;
|
||||
} catch (error) {
|
||||
showErrorModal(error as APIError);
|
||||
return false;
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import { useErrorModal } from 'providers/ErrorModalProvider';
|
||||
import APIError from 'types/api/error';
|
||||
|
||||
import { useOptimisticPatch } from '../../../hooks/useOptimisticPatch';
|
||||
import { compactGridItems } from '../../../layoutCompaction';
|
||||
import { replaceSectionItemsOp } from '../../../patchOps';
|
||||
import { useDashboardStore } from '../../../store/useDashboardStore';
|
||||
import type { GridItem } from '../../../utils';
|
||||
@@ -77,9 +76,7 @@ export function usePersistLayout({ layoutIndex, items }: Params): Result {
|
||||
if (!dashboardId) {
|
||||
return;
|
||||
}
|
||||
// Compact to the snapped, non-overlapping layout RGL shows on-screen, so
|
||||
// the persisted geometry can never trip the backend's no-overlap check.
|
||||
const nextItems = compactGridItems(mergeRglLayout(rglLayout, items));
|
||||
const nextItems = mergeRglLayout(rglLayout, items);
|
||||
if (!hasGeometryChanged(nextItems, items)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -86,47 +86,6 @@
|
||||
:global(.ant-select-selection-overflow) {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
// The shared NewSelect selector scrolls (max-height: 200px; overflow: auto),
|
||||
// which surfaces horizontal + vertical scrollbars inside the fixed-width
|
||||
// variable pill. Clip instead — the value is a single line (maxTagCount + "+N"),
|
||||
// so there is nothing to scroll to.
|
||||
:global(.ant-select-selector) {
|
||||
max-height: none !important;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
// Let the first tag shrink and truncate so the layout stays [tag…][+N]. Without
|
||||
// this the "+N" overflow item wins the row's space and the (longer) first tag
|
||||
// gets offset/clipped — visible after switching a value from ALL to a subset.
|
||||
:global(.ant-select-selection-overflow-item) {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
:global(.ant-select-selection-item) {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
// The shared .custom-multiselect forces the search box to a 60px floor
|
||||
// (min-width: 60px !important). In this narrow variable pill that reserved
|
||||
// width is what offsets/clips the tag row, so collapse it here — the extra
|
||||
// selectors out-specify the shared rule's !important. It still expands to fit
|
||||
// what the user types while the dropdown is open.
|
||||
:global(.ant-select-selector .ant-select-selection-search) {
|
||||
min-width: 0 !important;
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
|
||||
:global(
|
||||
.ant-select-selector
|
||||
.ant-select-selection-search
|
||||
.ant-select-selection-search-input
|
||||
) {
|
||||
min-width: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.overflowTooltip {
|
||||
|
||||
@@ -107,18 +107,6 @@ describe('reconcileWithOptions', () => {
|
||||
).toStrictEqual({ value: ['a', 'b'], allSelected: false });
|
||||
});
|
||||
|
||||
it('preserves a user-entered single value not in the options (freeform)', () => {
|
||||
// A typed value that isn't among the fetched options must survive a refetch
|
||||
// (e.g. a time-range change) rather than being reset to the default.
|
||||
expect(
|
||||
reconcileWithOptions(
|
||||
model({ type: 'QUERY' }),
|
||||
{ value: 'typed-value', allSelected: false },
|
||||
['a', 'b'],
|
||||
),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('falls back to the configured default (else first) when invalid', () => {
|
||||
expect(
|
||||
reconcileWithOptions(
|
||||
|
||||
@@ -1,12 +1,4 @@
|
||||
.addVariableNameWithIcon {
|
||||
flex: none;
|
||||
border-style: dashed !important;
|
||||
border-color: var(--l3-border) !important;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.addVariableIcon {
|
||||
.addVariable {
|
||||
flex: none;
|
||||
border-style: dashed !important;
|
||||
border-color: var(--l3-border) !important;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user