fix: render kafka consumer groups concisely
This commit is contained in:
@@ -103,6 +103,8 @@ interface PlatformKafkaConfig {
|
||||
management: {
|
||||
defaultTailLimit: number;
|
||||
maxTailLimit: number;
|
||||
defaultGroupListLimit: number;
|
||||
maxGroupListLimit: number;
|
||||
defaultShadowTopic: string;
|
||||
shadowProducerId: string;
|
||||
};
|
||||
@@ -189,7 +191,7 @@ export function kafkaHelp(): Record<string, unknown> {
|
||||
"bun scripts/cli.ts platform-infra kafka status --target NC01 [--full|--raw]",
|
||||
"bun scripts/cli.ts platform-infra kafka validate --target NC01 [--full|--raw]",
|
||||
"bun scripts/cli.ts platform-infra kafka topics --node NC01",
|
||||
"bun scripts/cli.ts platform-infra kafka groups --node NC01",
|
||||
"bun scripts/cli.ts platform-infra kafka groups --node NC01 [--limit N] [--full|--raw]",
|
||||
"bun scripts/cli.ts platform-infra kafka offsets --node NC01 [--topic hwlab.event.v1]",
|
||||
"bun scripts/cli.ts platform-infra kafka tail --node NC01 --topic hwlab.event.v1 --limit 5",
|
||||
"bun scripts/cli.ts platform-infra kafka produce --node NC01 --topic hwlab.event.v1 --key <trace-or-session>",
|
||||
@@ -317,6 +319,8 @@ function parseManagement(root: Record<string, unknown>): PlatformKafkaConfig["ma
|
||||
return {
|
||||
defaultTailLimit: positiveInteger(management, "defaultTailLimit", "management"),
|
||||
maxTailLimit: positiveInteger(management, "maxTailLimit", "management"),
|
||||
defaultGroupListLimit: positiveInteger(management, "defaultGroupListLimit", "management"),
|
||||
maxGroupListLimit: positiveInteger(management, "maxGroupListLimit", "management"),
|
||||
defaultShadowTopic: topicNameField(management, "defaultShadowTopic", "management"),
|
||||
shadowProducerId: y.stringField(management, "shadowProducerId", "management"),
|
||||
};
|
||||
@@ -332,6 +336,7 @@ function validateConfig(kafka: PlatformKafkaConfig): void {
|
||||
if (!kafka.topics.some((topic) => topic.name === kafka.validation.smokeTopic)) throw new Error(`${configLabel}.validation.smokeTopic must reference one of topics[].name`);
|
||||
if (!kafka.topics.some((topic) => topic.name === kafka.management.defaultShadowTopic)) throw new Error(`${configLabel}.management.defaultShadowTopic must reference one of topics[].name`);
|
||||
if (kafka.management.defaultTailLimit > kafka.management.maxTailLimit) throw new Error(`${configLabel}.management.defaultTailLimit must be <= management.maxTailLimit`);
|
||||
if (kafka.management.defaultGroupListLimit > kafka.management.maxGroupListLimit) throw new Error(`${configLabel}.management.defaultGroupListLimit must be <= management.maxGroupListLimit`);
|
||||
if (kafka.defaults.switch.shadowConsumeEnabled) throw new Error(`${configLabel}.defaults.switch.shadowConsumeEnabled must stay false for shadow-produce-only stage`);
|
||||
const topicNames = new Set<string>();
|
||||
for (const topic of kafka.topics) {
|
||||
@@ -480,6 +485,7 @@ async function topics(config: UniDeskConfig, options: KafkaInspectOptions): Prom
|
||||
async function groups(config: UniDeskConfig, options: KafkaInspectOptions): Promise<Record<string, unknown>> {
|
||||
const kafka = readKafkaConfig();
|
||||
const target = resolveTarget(kafka, options.targetId);
|
||||
const limit = boundedGroupListLimit(kafka, options.limit);
|
||||
const result = await capture(config, target.route, ["sh"], groupsScript(kafka, target));
|
||||
const parsed = parseJsonOutput(result.stdout);
|
||||
return {
|
||||
@@ -489,6 +495,7 @@ async function groups(config: UniDeskConfig, options: KafkaInspectOptions): Prom
|
||||
target: targetSummary(target),
|
||||
config: compactConfigSummary(kafka, target),
|
||||
query: parsed ?? null,
|
||||
presentation: { limit },
|
||||
remote: options.raw && parsed !== null ? parsed : compactCapture(result, { full: options.full || result.exitCode !== 0 }),
|
||||
};
|
||||
}
|
||||
@@ -1415,6 +1422,8 @@ function compactConfigSummary(kafka: PlatformKafkaConfig, target: KafkaTarget):
|
||||
defaultShadowTopic: kafka.management.defaultShadowTopic,
|
||||
defaultTailLimit: kafka.management.defaultTailLimit,
|
||||
maxTailLimit: kafka.management.maxTailLimit,
|
||||
defaultGroupListLimit: kafka.management.defaultGroupListLimit,
|
||||
maxGroupListLimit: kafka.management.maxGroupListLimit,
|
||||
shadowProducerId: kafka.management.shadowProducerId,
|
||||
},
|
||||
valuesPrinted: false,
|
||||
@@ -1612,13 +1621,25 @@ function renderTopics(result: Record<string, unknown>): RenderedCliResult {
|
||||
|
||||
function renderGroups(result: Record<string, unknown>): RenderedCliResult {
|
||||
const query = record(result.query);
|
||||
const groups = arrayRecords(query.groups).length > 0 ? arrayRecords(query.groups).map((item) => [stringValue(item.name)]) : (Array.isArray(query.groups) ? query.groups.map((item) => [String(item)]) : []);
|
||||
const presentation = record(result.presentation);
|
||||
const limit = Number(presentation.limit);
|
||||
const names = Array.isArray(query.groups)
|
||||
? query.groups.flatMap((item) => {
|
||||
if (typeof item === "string" && item.length > 0) return [item];
|
||||
const value = record(item).name;
|
||||
return typeof value === "string" && value.length > 0 ? [value] : [];
|
||||
})
|
||||
: [];
|
||||
const shown = names.slice(0, Number.isInteger(limit) && limit > 0 ? limit : names.length);
|
||||
return rendered(result, "platform-infra kafka groups", [
|
||||
"PLATFORM-INFRA KAFKA GROUPS",
|
||||
...table(["TARGET", "NAMESPACE", "CLUSTER", "POD"], [[stringValue(query.target), stringValue(query.namespace), stringValue(query.cluster), stringValue(query.pod)]]),
|
||||
"",
|
||||
...(groups.length === 0 ? ["GROUPS -"] : table(["GROUP"], groups)),
|
||||
...table(["TOTAL", "SHOWN", "OMITTED"], [[String(names.length), String(shown.length), String(Math.max(0, names.length - shown.length))]]),
|
||||
"",
|
||||
...(shown.length === 0 ? ["GROUPS -"] : table(["GROUP"], shown.map((name) => [name]))),
|
||||
...remoteErrorLines(result),
|
||||
...(names.length > shown.length ? ["", `NEXT bun scripts/cli.ts platform-infra kafka groups --node ${stringValue(query.target)} --raw`] : []),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -1804,6 +1825,13 @@ function boundedLimit(kafka: PlatformKafkaConfig, limit: number | null): number
|
||||
return value;
|
||||
}
|
||||
|
||||
function boundedGroupListLimit(kafka: PlatformKafkaConfig, limit: number | null): number {
|
||||
const value = limit ?? kafka.management.defaultGroupListLimit;
|
||||
if (!Number.isInteger(value) || value < 1) throw new Error("group list limit must be a positive integer");
|
||||
if (value > kafka.management.maxGroupListLimit) throw new Error(`limit ${value} exceeds ${configLabel}.management.maxGroupListLimit=${kafka.management.maxGroupListLimit}`);
|
||||
return value;
|
||||
}
|
||||
|
||||
function buildShadowPayload(kafka: PlatformKafkaConfig, target: KafkaTarget, options: KafkaProduceOptions, topic: string): string {
|
||||
let userPayload: unknown = null;
|
||||
if (options.payload !== null) {
|
||||
|
||||
@@ -453,7 +453,7 @@ export function platformInfraHelp(): unknown {
|
||||
"bun scripts/cli.ts platform-infra kafka status --target NC01",
|
||||
"bun scripts/cli.ts platform-infra kafka validate --target NC01",
|
||||
"bun scripts/cli.ts platform-infra kafka topics --node NC01",
|
||||
"bun scripts/cli.ts platform-infra kafka groups --node NC01",
|
||||
"bun scripts/cli.ts platform-infra kafka groups --node NC01 [--limit N] [--full|--raw]",
|
||||
"bun scripts/cli.ts platform-infra kafka offsets --node NC01 --topic hwlab.event.v1",
|
||||
"bun scripts/cli.ts platform-infra kafka tail --node NC01 --topic hwlab.event.v1 --limit 5",
|
||||
"bun scripts/cli.ts platform-infra kafka produce --node NC01 --topic hwlab.event.v1 --key <trace-or-session>",
|
||||
|
||||
Reference in New Issue
Block a user