Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tolerate missing metrics, use alternate metric from replica count #475

Merged
merged 1 commit into from
Feb 14, 2024
Merged
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
2 changes: 1 addition & 1 deletion ui/api/kafka/kpi.promql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ or
sum by (__console_metric_name__, nodeId) (
label_replace(
label_replace(
kafka_cluster_partition_replicascount{namespace="${namespace}",pod=~"${cluster}-.+-\\\\d+",strimzi_io_kind="Kafka"} > 0,
kafka_server_replicamanager_partitioncount{namespace="${namespace}",pod=~"${cluster}-.+-\\\\d+",strimzi_io_kind="Kafka"} > 0,
"nodeId",
"$1",
"pod",
Expand Down
34 changes: 17 additions & 17 deletions ui/api/kafka/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,28 +59,28 @@ export const ClusterResponse = z.object({
export type ClusterDetail = z.infer<typeof ClusterDetailSchema>;

export const ClusterKpisSchema = z.object({
broker_state: z.record(z.number()),
total_topics: z.number(),
total_partitions: z.number(),
underreplicated_topics: z.number(),
broker_state: z.record(z.number()).optional(),
total_topics: z.number().optional(),
total_partitions: z.number().optional(),
underreplicated_topics: z.number().optional(),
replica_count: z.object({
byNode: z.record(z.number()),
total: z.number(),
}),
byNode: z.record(z.number()).optional(),
total: z.number().optional(),
}).optional(),
leader_count: z.object({
byNode: z.record(z.number()),
total: z.number(),
}),
byNode: z.record(z.number()).optional(),
total: z.number().optional(),
}).optional(),
volume_stats_capacity_bytes: z.object({
byNode: z.record(z.number()),
total: z.number(),
}),
byNode: z.record(z.number()).optional(),
total: z.number().optional(),
}).optional(),
volume_stats_used_bytes: z.object({
byNode: z.record(z.number()),
total: z.number(),
}),
byNode: z.record(z.number()).optional(),
total: z.number().optional(),
}).optional(),
});
export type ClusterKpis = z.infer<typeof ClusterKpisSchema>;

export const MetricRangeSchema = z.record(z.string(), z.record(z.number()));
export const MetricRangeSchema = z.record(z.string(), z.record(z.number()).optional());
export type MetricRange = z.infer<typeof MetricRangeSchema>;
14 changes: 9 additions & 5 deletions ui/app/[locale]/kafka/[kafkaId]/nodes/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import {
import { PageSection } from "@/libs/patternfly/react-core";
import { redirect } from "@/navigation";

function nodeMetric(metrics: Record<string, number> | undefined, nodeId: number): number {
return metrics ? (metrics[nodeId.toString()] ?? 0) : 0;
}

export default async function NodesPage({ params }: { params: KafkaParams }) {
const res = await getKafkaClusterKpis(params.kafkaId);
if (!res) {
Expand All @@ -20,11 +24,11 @@ export default async function NodesPage({ params }: { params: KafkaParams }) {
}

const nodes: Node[] = cluster.attributes.nodes.map((node) => {
const status = kpis.broker_state[node.id] === 3 ? "Stable" : "Unstable";
const leaders = kpis.leader_count.byNode[node.id];
const followers = kpis.replica_count.byNode[node.id] - leaders;
const diskCapacity = kpis.volume_stats_capacity_bytes.byNode[node.id];
const diskUsage = kpis.volume_stats_used_bytes.byNode[node.id];
const status = nodeMetric(kpis.broker_state, node.id) === 3 ? "Stable" : "Unstable";
const leaders = nodeMetric(kpis.leader_count?.byNode, node.id);
const followers = nodeMetric(kpis.replica_count?.byNode, node.id) - leaders;
const diskCapacity = nodeMetric(kpis.volume_stats_capacity_bytes?.byNode, node.id);
const diskUsage = nodeMetric(kpis.volume_stats_used_bytes?.byNode, node.id);
return {
id: node.id,
status,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import { useFormatter } from "next-intl";
import { useChartWidth } from "./useChartWidth";

type ChartIncomingOutgoingProps = {
incoming: Record<string, TimeSeriesMetrics>;
outgoing: Record<string, TimeSeriesMetrics>;
incoming: Record<string, TimeSeriesMetrics | undefined>;
outgoing: Record<string, TimeSeriesMetrics | undefined>;
};

type Datum = {
Expand All @@ -42,7 +42,7 @@ export function ChartIncomingOutgoing({
const hasMetrics =
Object.keys(incoming).length > 0 && Object.keys(outgoing).length > 0;
if (!hasMetrics) {
return <div>TODO</div>;
return <div><i>Not available</i></div>;
}
// const showDate = shouldShowDate(duration);
const CursorVoronoiContainer = createContainer("voronoi", "cursor");
Expand Down Expand Up @@ -124,7 +124,7 @@ export function ChartIncomingOutgoing({
/>
<ChartGroup>
{Object.entries(incoming).map(([name, entries], idx) => {
const entriesArray = Object.entries(entries);
const entriesArray = Object.entries(entries ?? {});
return (
<ChartArea
key={`incoming-line-${name}}`}
Expand All @@ -140,8 +140,8 @@ export function ChartIncomingOutgoing({
);
})}
{Object.entries(outgoing).map(([name, entries], idx) => {
const entriesArray = Object.entries(entries);
const incomingArray = Object.keys(incoming[name]);
const entriesArray = Object.entries(entries ?? {});
const incomingArray = Object.keys(incoming[name] ?? {});
return (
<ChartArea
key={`outgoing-line-${name}}`}
Expand Down
12 changes: 8 additions & 4 deletions ui/app/[locale]/kafka/[kafkaId]/overview/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ async function ConnectedTopicsPartitionsCard({
);
}

function timeSeriesMetrics(ranges: Record<ClusterMetric, MetricRange> | undefined, rangeName: ClusterMetric) : TimeSeriesMetrics[] {
return ranges ? Object.values(ranges[rangeName] ?? {}).map(val => val ?? {}) : [];
}

async function ConnectedClusterChartsCard({
data,
}: {
Expand All @@ -112,10 +116,10 @@ async function ConnectedClusterChartsCard({
<>
<ClusterChartsCard
isLoading={false}
usedDiskSpace={Object.values(res?.ranges["volumeUsed"] || {})}
availableDiskSpace={Object.values(res?.ranges["volumeCapacity"] || {})}
memoryUsage={Object.values(res?.ranges["memory"] || {})}
cpuUsage={Object.values(res?.ranges["cpu"] || {})}
usedDiskSpace={ timeSeriesMetrics(res?.ranges, "volumeUsed") }
availableDiskSpace={ timeSeriesMetrics(res?.ranges, "volumeCapacity") }
memoryUsage={ timeSeriesMetrics(res?.ranges, "memory") }
cpuUsage={ timeSeriesMetrics(res?.ranges, "cpu") }
/>
</>
);
Expand Down