Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
const clusterApi = new ClustersApi()
const alertRulesApi = new AlertRulesApi()
const alertReceiversApi = new AlertReceiversApi()
const organizationApi = new OrganizationMainCallsApi()

export const observability = createQueryKeys('observability', {
containerName: ({
Expand Down Expand Up @@ -167,6 +166,40 @@ export const observability = createQueryKeys('observability', {
return response.data.metrics && (JSON.parse(response.data.metrics).data[0] as string)
},
}),
podNames: ({
clusterId,
statefulsetName,
startDate,
endDate,
}: {
clusterId: string
statefulsetName: string
startDate: string
endDate: string
}) => ({
queryKey: ['podNames', clusterId, statefulsetName],
async queryFn() {
const endpoint = `api/v1/label/pod/values?match[]=kube_pod_owner{owner_kind="StatefulSet",owner_name="${statefulsetName}"}`
const response = await clusterApi.getClusterMetrics(
clusterId,
endpoint,
'',
startDate,
endDate,
undefined,
undefined,
undefined,
'True',
'True',
undefined,
'prometheus',
'false',
'service_overview',
'pod_names'
)
return response.data.metrics && (JSON.parse(response.data.metrics).data as string[])
},
}),
metrics: ({
clusterId,
query,
Expand Down
1 change: 1 addition & 0 deletions libs/domains/observability/feature/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export * from './lib/hooks/use-edit-alert-rule/use-edit-alert-rule'
export * from './lib/hooks/use-alert-rules/use-alert-rules'
export * from './lib/hooks/use-environment/use-environment'
export * from './lib/hooks/use-container-name/use-container-name'
export * from './lib/hooks/use-pod-names/use-pod-names'
export * from './lib/hooks/use-ingress-name/use-ingress-name'
export * from './lib/hooks/use-hpa-name/use-hpa-name'
export * from './lib/hooks/use-alerts/use-alerts'
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useQuery } from '@tanstack/react-query'
import { observability } from '@qovery/domains/observability/data-access'

export interface UsePodNamesProps {
clusterId: string
statefulsetName: string
startDate: string
endDate: string
enabled?: boolean
}

// Retrieves pod names for a StatefulSet using kube_pod_owner
export function usePodNames({ clusterId, statefulsetName, startDate, endDate, enabled = true }: UsePodNamesProps) {
return useQuery({
...observability.podNames({ clusterId, statefulsetName, startDate, endDate }),
enabled: enabled && Boolean(clusterId && statefulsetName),
retry: enabled ? undefined : false,
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,13 @@ export function CardInstanceStatus({
clusterId,
containerName,
namespace,
podNames,
}: {
serviceId: string
clusterId: string
containerName: string
namespace: string
podNames?: string[]
}) {
const { queryTimeRange, subQueryTimeRange, startTimestamp, endTimestamp } = useDashboardContext()
const [isModalOpen, setIsModalOpen] = useState(false)
Expand Down Expand Up @@ -134,6 +136,7 @@ export function CardInstanceStatus({
serviceId={serviceId}
containerName={containerName}
namespace={namespace}
podNames={podNames}
/>
</div>
</Section>
Expand All @@ -146,6 +149,7 @@ export function CardInstanceStatus({
containerName={containerName}
isFullscreen
namespace={namespace}
podNames={podNames}
/>
</div>
</ModalChart>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export function CardStorage({ serviceId, clusterId }: { serviceId: string; clust
})

const rawValue = Number(metricsPercentage?.data?.result[0]?.value[1])
const value = Number.isFinite(rawValue) ? Math.round(rawValue) : 0
const value = Number.isFinite(rawValue) ? rawValue : 0

const maxUsageBytes = Number(metricsMaxStorage?.data?.result[0]?.value[1])

Expand All @@ -89,8 +89,14 @@ export function CardStorage({ serviceId, clusterId }: { serviceId: string; clust
const totalStorageGiB = value > 0 ? maxUsageGiB / (value / 100) : 0

const title = `${maxUsageDisplay} ${maxUsageUnit} max storage usage`
const description =
value > 0 ? `${value}% of your ${totalStorageGiB.toFixed(1)} GiB storage allowance` : `No storage usage data`

let description
if (value > 0) {
const displayValue = value < 0.01 ? '< 0.01' : value < 1 ? value.toFixed(2) : Math.round(value).toString()
description = `${displayValue}% of your ${totalStorageGiB.toFixed(1)} GiB storage allowance`
} else {
description = 'No storage usage data'
}

return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,30 @@ import { usePodColor } from '@qovery/shared/util-hooks'
import { calculateRateInterval, useMetrics } from '../../../hooks/use-metrics/use-metrics'
import { LocalChart } from '../../../local-chart/local-chart'
import { addTimeRangePadding } from '../../../util-chart/add-time-range-padding'
import { buildPromSelector } from '../../../util-chart/build-selector'
import { convertPodName } from '../../../util-chart/convert-pod-name'
import { processMetricsData } from '../../../util-chart/process-metrics-data'
import { useDashboardContext } from '../../../util-filter/dashboard-context'

const queryCpuUsage = (rateInterval: string, containerName: string) => `
sum by (pod) (rate(container_cpu_usage_seconds_total{container="${containerName}"}[${rateInterval}]))
`
const queryCpuUsage = (rateInterval: string, selector: string) =>
`sum by (pod) (rate(container_cpu_usage_seconds_total{${selector}}[${rateInterval}]))`

const queryCpuLimit = (containerName: string) => `
sum (bottomk(1, kube_pod_container_resource_limits{resource="cpu",container="${containerName}"}))
`
const queryCpuLimit = (selector: string) =>
`sum (bottomk(1, kube_pod_container_resource_limits{resource="cpu",${selector}}))`

const queryCpuRequest = (containerName: string) => `
sum (bottomk(1, kube_pod_container_resource_requests{resource="cpu",container="${containerName}"}))
`
const queryCpuRequest = (selector: string) =>
`sum (bottomk(1, kube_pod_container_resource_requests{resource="cpu",${selector}}))`

export function CpuChart({
clusterId,
serviceId,
containerName,
podNames,
}: {
clusterId: string
serviceId: string
containerName: string
podNames?: string[]
}) {
const { startTimestamp, endTimestamp, useLocalTime, timeRange } = useDashboardContext()
const getColorByPod = usePodColor()
Expand Down Expand Up @@ -56,9 +56,11 @@ export function CpuChart({
[startTimestamp, endTimestamp]
)

const selector = useMemo(() => buildPromSelector(containerName, podNames), [containerName, podNames])

const { data: metrics, isLoading: isLoadingMetrics } = useMetrics({
clusterId,
query: queryCpuUsage(rateInterval, containerName),
query: queryCpuUsage(rateInterval, selector),
startTimestamp,
endTimestamp,
timeRange,
Expand All @@ -68,7 +70,7 @@ export function CpuChart({

const { data: limitMetrics, isLoading: isLoadingLimit } = useMetrics({
clusterId,
query: queryCpuLimit(containerName),
query: queryCpuLimit(selector),
startTimestamp,
endTimestamp,
timeRange,
Expand All @@ -78,7 +80,7 @@ export function CpuChart({

const { data: requestMetrics, isLoading: isLoadingRequest } = useMetrics({
clusterId,
query: queryCpuRequest(containerName),
query: queryCpuRequest(selector),
startTimestamp,
endTimestamp,
timeRange,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,42 @@ import { Line } from 'recharts'
import { useMetrics } from '../../../hooks/use-metrics/use-metrics'
import { LocalChart } from '../../../local-chart/local-chart'
import { addTimeRangePadding } from '../../../util-chart/add-time-range-padding'
import { buildPromSelector } from '../../../util-chart/build-selector'
import { processMetricsData } from '../../../util-chart/process-metrics-data'
import { useDashboardContext } from '../../../util-filter/dashboard-context'

const queryDiskReadNvme = (containerName: string) => `
sum by (device) (rate(container_fs_reads_bytes_total{container="${containerName}", device=~"/dev/nvme0.*"}[1m]))
`
const queryDiskReadNvme = (selector: string) =>
`sum (rate(container_fs_reads_bytes_total{${selector}, device=~"/dev/nvme.*"}[1m]))`

const queryDiskReadNonNvme = (containerName: string) => `
sum by (device) (rate(container_fs_reads_bytes_total{container="${containerName}", device!~"/dev/nvme0.*", device!=""}[1m]))
`
const queryDiskReadNonNvme = (selector: string) =>
`sum by (device) (rate(container_fs_reads_bytes_total{${selector}, device!~"/dev/nvme.*", device!=""}[1m]))`

const queryDiskWriteNvme = (containerName: string) => `
sum by (device) (rate(container_fs_writes_bytes_total{container="${containerName}", device=~"/dev/nvme0.*"}[1m]))
`
const queryDiskWriteNvme = (selector: string) =>
`sum by (device) (rate(container_fs_writes_bytes_total{${selector}, device=~"/dev/nvme.*"}[1m]))`

const queryDiskWriteNonNvme = (containerName: string) => `
sum by (device) (rate(container_fs_writes_bytes_total{container=${containerName}"", device!~"/dev/nvme0.*", device!=""}[1m]))
`
const queryDiskWriteNonNvme = (selector: string) =>
`sum by (device) (rate(container_fs_writes_bytes_total{${selector}, device!~"/dev/nvme.*", device!=""}[1m]))`

export function DiskChart({
clusterId,
serviceId,
containerName,
podNames,
}: {
clusterId: string
serviceId: string
containerName: string
podNames?: string[]
}) {
const { startTimestamp, endTimestamp, useLocalTime, timeRange } = useDashboardContext()

const selector = useMemo(() => buildPromSelector(containerName, podNames), [containerName, podNames])

const { data: metricsReadEphemeralStorage, isLoading: isLoadingMetricsReadEphemeralStorage } = useMetrics({
clusterId,
startTimestamp,
endTimestamp,
query: queryDiskReadNvme(containerName),
query: queryDiskReadNvme(selector),
timeRange,
boardShortName: 'service_overview',
metricShortName: 'disk_chart_read_ephemeral',
Expand All @@ -47,7 +48,7 @@ export function DiskChart({
clusterId,
startTimestamp,
endTimestamp,
query: queryDiskReadNonNvme(containerName),
query: queryDiskReadNonNvme(selector),
timeRange,
boardShortName: 'service_overview',
metricShortName: 'disk_chart_read_persistent',
Expand All @@ -57,7 +58,7 @@ export function DiskChart({
clusterId,
startTimestamp,
endTimestamp,
query: queryDiskWriteNvme(containerName),
query: queryDiskWriteNvme(selector),
timeRange,
boardShortName: 'service_overview',
metricShortName: 'disk_chart_read_ephemeral',
Expand All @@ -67,7 +68,7 @@ export function DiskChart({
clusterId,
startTimestamp,
endTimestamp,
query: queryDiskWriteNonNvme(containerName),
query: queryDiskWriteNonNvme(selector),
timeRange,
boardShortName: 'service_overview',
metricShortName: 'disk_chart_write_persistent',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Area, Line, ReferenceLine } from 'recharts'
import { calculateDynamicRange, calculateRateInterval, useMetrics } from '../../../hooks/use-metrics/use-metrics'
import { LocalChart, type ReferenceLineEvent } from '../../../local-chart/local-chart'
import { addTimeRangePadding } from '../../../util-chart/add-time-range-padding'
import { buildPromSelector } from '../../../util-chart/build-selector'
import { formatTimestamp } from '../../../util-chart/format-timestamp'
import { processMetricsData } from '../../../util-chart/process-metrics-data'
import { useDashboardContext } from '../../../util-filter/dashboard-context'
Expand All @@ -15,20 +16,20 @@ sum by (condition) (
)
`

const queryRestartWithReason = (containerName: string, timeRange: string) => `
sum by (reason) (
sum by (pod) (
increase(kube_pod_container_status_restarts_total{container="${containerName}"}[${timeRange}])
)
*
on(pod) group_left(reason)
sum by (pod, reason) (
max without(instance, job, endpoint, service, prometheus, uid) (
kube_pod_container_status_last_terminated_reason{container="${containerName}"}
)
)
)
`
const queryRestartWithReason = (selector: string, timeRange: string) => `
sum by (reason) (
sum by (pod) (
increase(kube_pod_container_status_restarts_total{${selector}}[${timeRange}])
)
*
on(pod) group_left(reason)
sum by (pod, reason) (
max without(instance, job, endpoint, service, prometheus, uid) (
kube_pod_container_status_last_terminated_reason{${selector}}
)
)
)
`

const queryK8sEvent = (serviceId: string, dynamicRange: string) => `
sum by (pod,reason)(
Expand Down Expand Up @@ -199,12 +200,14 @@ export function InstanceStatusChart({
containerName,
isFullscreen,
namespace,
podNames,
}: {
clusterId: string
serviceId: string
containerName: string
namespace: string
isFullscreen?: boolean
podNames?: string[]
}) {
const { startTimestamp, endTimestamp, useLocalTime, hideEvents, timeRange } = useDashboardContext()

Expand All @@ -230,6 +233,8 @@ export function InstanceStatusChart({
metricShortName: 'instance_status_health',
})

const selector = useMemo(() => buildPromSelector(containerName, podNames), [containerName, podNames])

const {
data: metricsRestartsWithReason,
isLoading: isLoadingMetricsRestartsWithReason,
Expand All @@ -239,7 +244,7 @@ export function InstanceStatusChart({
startTimestamp,
endTimestamp,
timeRange,
query: queryRestartWithReason(containerName, timeRange),
query: queryRestartWithReason(selector, timeRange),
boardShortName: 'service_overview',
metricShortName: 'instance_status_restart',
})
Expand Down
Loading