Skip to content

Commit 8272719

Browse files
committed
Move utils to util file
1 parent 923263e commit 8272719

File tree

2 files changed

+111
-118
lines changed

2 files changed

+111
-118
lines changed

src/common/atlas/performanceAdvisorUtils.ts

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,106 @@ export async function getSlowQueries(
258258
throw new Error(`Failed to list slow query logs: ${err instanceof Error ? err.message : String(err)}`);
259259
}
260260
}
261+
262+
export function formatSuggestedIndexesTable(suggestedIndexes: Array<SuggestedIndex>): string {
263+
if (suggestedIndexes.length === 0) return "No suggested indexes found.";
264+
265+
const rows = suggestedIndexes
266+
.map((index, i) => {
267+
const namespace = index.namespace ?? "N/A";
268+
const weight = index.weight ?? "N/A";
269+
const avgObjSize = index.avgObjSize ?? "N/A";
270+
const indexKeys = index.index ? index.index.map((key) => Object.keys(key)[0]).join(", ") : "N/A";
271+
return `${i + 1} | ${namespace} | ${weight} | ${avgObjSize} | ${indexKeys}`;
272+
})
273+
.join("\n");
274+
275+
return `# | Namespace | Weight | Avg Obj Size | Index Keys
276+
---|-----------|--------|--------------|------------
277+
${rows}`;
278+
}
279+
280+
export function formatDropIndexesTable(dropIndexSuggestions: {
281+
hiddenIndexes: Array<DropIndexSuggestion>;
282+
redundantIndexes: Array<DropIndexSuggestion>;
283+
unusedIndexes: Array<DropIndexSuggestion>;
284+
}): string {
285+
const allIndexes = [
286+
...dropIndexSuggestions.hiddenIndexes.map((idx) => ({ ...idx, type: "Hidden" })),
287+
...dropIndexSuggestions.redundantIndexes.map((idx) => ({ ...idx, type: "Redundant" })),
288+
...dropIndexSuggestions.unusedIndexes.map((idx) => ({ ...idx, type: "Unused" })),
289+
];
290+
291+
if (allIndexes.length === 0) return "No drop index suggestions found.";
292+
293+
const rows = allIndexes
294+
.map((index, i) => {
295+
const name = index.name ?? "N/A";
296+
const namespace = index.namespace ?? "N/A";
297+
const type = index.type ?? "N/A";
298+
const sizeBytes = index.sizeBytes ?? "N/A";
299+
const accessCount = index.accessCount ?? "N/A";
300+
return `${i + 1} | ${name} | ${namespace} | ${type} | ${sizeBytes} | ${accessCount}`;
301+
})
302+
.join("\n");
303+
304+
return `# | Index Name | Namespace | Type | Size (bytes) | Access Count
305+
---|------------|-----------|------|--------------|-------------
306+
${rows}`;
307+
}
308+
309+
export function formatSlowQueriesTable(slowQueryLogs: Array<SlowQueryLog>): string {
310+
if (slowQueryLogs.length === 0) return "No slow query logs found.";
311+
312+
const rows = slowQueryLogs
313+
.map((log, i) => {
314+
const namespace = log.namespace ?? "N/A";
315+
const opType = log.opType ?? "N/A";
316+
const executionTime = log.metrics?.operationExecutionTime ?? "N/A";
317+
const docsExamined = log.metrics?.docsExamined ?? "N/A";
318+
const docsReturned = log.metrics?.docsReturned ?? "N/A";
319+
return `${i + 1} | ${namespace} | ${opType} | ${executionTime}ms | ${docsExamined} | ${docsReturned}`;
320+
})
321+
.join("\n");
322+
323+
return `# | Namespace | Operation | Execution Time | Docs Examined | Docs Returned
324+
---|-----------|-----------|---------------|---------------|---------------
325+
${rows}`;
326+
}
327+
328+
function getTriggerDescription(triggerType: SchemaTriggerType | undefined): string {
329+
if (!triggerType) return "N/A";
330+
return SCHEMA_TRIGGER_DESCRIPTIONS[triggerType] ?? triggerType;
331+
}
332+
333+
function getNamespaceTriggerDescriptions(namespace: { triggers?: Array<{ triggerType?: SchemaTriggerType }> }): string {
334+
if (!namespace.triggers) return "N/A";
335+
336+
return namespace.triggers.map((trigger) => getTriggerDescription(trigger.triggerType)).join(", ");
337+
}
338+
339+
function getTriggerDescriptions(suggestion: SchemaRecommendation): string {
340+
if (!suggestion.affectedNamespaces) return "N/A";
341+
342+
return suggestion.affectedNamespaces.map((namespace) => getNamespaceTriggerDescriptions(namespace)).join(", ");
343+
}
344+
345+
export function formatSchemaSuggestionsTable(schemaSuggestions: Array<SchemaRecommendation>): string {
346+
if (schemaSuggestions.length === 0) return "No schema suggestions found.";
347+
348+
const rows = schemaSuggestions
349+
.map((suggestion: SchemaRecommendation, i) => {
350+
const recommendation = suggestion.recommendation
351+
? (SCHEMA_RECOMMENDATION_DESCRIPTIONS[suggestion.recommendation] ?? suggestion.recommendation)
352+
: "N/A";
353+
const description = suggestion.description ?? "N/A";
354+
const triggeredBy = getTriggerDescriptions(suggestion);
355+
const affectedNamespaces = suggestion.affectedNamespaces?.length ?? 0;
356+
return `${i + 1} | ${recommendation} | ${description} | ${triggeredBy} | ${affectedNamespaces} namespaces`;
357+
})
358+
.join("\n");
359+
360+
return `# | Recommendation | Description | Triggered By | Affected Namespaces
361+
---|---------------|-------------|----------|-------------------
362+
${rows}`;
363+
}

src/tools/atlas/read/listPerformanceAdvisor.ts

Lines changed: 8 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,10 @@ import {
1010
getSlowQueries,
1111
PerformanceAdvisorOperation,
1212
type PerformanceAdvisorData,
13-
type SuggestedIndex,
14-
type DropIndexSuggestion,
15-
type SlowQueryLog,
16-
type SchemaRecommendation,
17-
SCHEMA_RECOMMENDATION_DESCRIPTIONS,
18-
SCHEMA_TRIGGER_DESCRIPTIONS,
19-
type SchemaTriggerType,
13+
formatSuggestedIndexesTable,
14+
formatDropIndexesTable,
15+
formatSlowQueriesTable,
16+
formatSchemaSuggestionsTable,
2017
} from "../../../common/atlas/performanceAdvisorUtils.js";
2118

2219
export class ListPerformanceAdvisorTool extends AtlasToolBase {
@@ -35,113 +32,6 @@ export class ListPerformanceAdvisorTool extends AtlasToolBase {
3532
namespaces: z.array(z.string()).describe("Namespaces to list slow query logs").optional(),
3633
};
3734

38-
private formatSuggestedIndexesTable(suggestedIndexes: Array<SuggestedIndex>): string {
39-
if (suggestedIndexes.length === 0) return "No suggested indexes found.";
40-
41-
const rows = suggestedIndexes
42-
.map((index, i) => {
43-
const namespace = index.namespace ?? "N/A";
44-
const weight = index.weight ?? "N/A";
45-
const avgObjSize = index.avgObjSize ?? "N/A";
46-
const indexKeys = index.index ? index.index.map((key) => Object.keys(key)[0]).join(", ") : "N/A";
47-
return `${i + 1} | ${namespace} | ${weight} | ${avgObjSize} | ${indexKeys}`;
48-
})
49-
.join("\n");
50-
51-
return `# | Namespace | Weight | Avg Obj Size | Index Keys
52-
---|-----------|--------|--------------|------------
53-
${rows}`;
54-
}
55-
56-
private formatDropIndexesTable(dropIndexSuggestions: {
57-
hiddenIndexes: Array<DropIndexSuggestion>;
58-
redundantIndexes: Array<DropIndexSuggestion>;
59-
unusedIndexes: Array<DropIndexSuggestion>;
60-
}): string {
61-
const allIndexes = [
62-
...dropIndexSuggestions.hiddenIndexes.map((idx) => ({ ...idx, type: "Hidden" })),
63-
...dropIndexSuggestions.redundantIndexes.map((idx) => ({ ...idx, type: "Redundant" })),
64-
...dropIndexSuggestions.unusedIndexes.map((idx) => ({ ...idx, type: "Unused" })),
65-
];
66-
67-
if (allIndexes.length === 0) return "No drop index suggestions found.";
68-
69-
const rows = allIndexes
70-
.map((index, i) => {
71-
const name = index.name ?? "N/A";
72-
const namespace = index.namespace ?? "N/A";
73-
const type = index.type ?? "N/A";
74-
const sizeBytes = index.sizeBytes ?? "N/A";
75-
const accessCount = index.accessCount ?? "N/A";
76-
return `${i + 1} | ${name} | ${namespace} | ${type} | ${sizeBytes} | ${accessCount}`;
77-
})
78-
.join("\n");
79-
80-
return `# | Index Name | Namespace | Type | Size (bytes) | Access Count
81-
---|------------|-----------|------|--------------|-------------
82-
${rows}`;
83-
}
84-
85-
private formatSlowQueriesTable(slowQueryLogs: Array<SlowQueryLog>): string {
86-
if (slowQueryLogs.length === 0) return "No slow query logs found.";
87-
88-
const rows = slowQueryLogs
89-
.map((log, i) => {
90-
const namespace = log.namespace ?? "N/A";
91-
const opType = log.opType ?? "N/A";
92-
const executionTime = log.metrics?.operationExecutionTime ?? "N/A";
93-
const docsExamined = log.metrics?.docsExamined ?? "N/A";
94-
const docsReturned = log.metrics?.docsReturned ?? "N/A";
95-
return `${i + 1} | ${namespace} | ${opType} | ${executionTime}ms | ${docsExamined} | ${docsReturned}`;
96-
})
97-
.join("\n");
98-
99-
return `# | Namespace | Operation | Execution Time | Docs Examined | Docs Returned
100-
---|-----------|-----------|---------------|---------------|---------------
101-
${rows}`;
102-
}
103-
104-
private getTriggerDescription(triggerType: SchemaTriggerType | undefined): string {
105-
if (!triggerType) return "N/A";
106-
return SCHEMA_TRIGGER_DESCRIPTIONS[triggerType] ?? triggerType;
107-
}
108-
109-
private getNamespaceTriggerDescriptions(namespace: {
110-
triggers?: Array<{ triggerType?: SchemaTriggerType }>;
111-
}): string {
112-
if (!namespace.triggers) return "N/A";
113-
114-
return namespace.triggers.map((trigger) => this.getTriggerDescription(trigger.triggerType)).join(", ");
115-
}
116-
117-
private getTriggerDescriptions(suggestion: SchemaRecommendation): string {
118-
if (!suggestion.affectedNamespaces) return "N/A";
119-
120-
return suggestion.affectedNamespaces
121-
.map((namespace) => this.getNamespaceTriggerDescriptions(namespace))
122-
.join(", ");
123-
}
124-
125-
private formatSchemaSuggestionsTable(schemaSuggestions: Array<SchemaRecommendation>): string {
126-
if (schemaSuggestions.length === 0) return "No schema suggestions found.";
127-
128-
const rows = schemaSuggestions
129-
.map((suggestion: SchemaRecommendation, i) => {
130-
const recommendation = suggestion.recommendation
131-
? (SCHEMA_RECOMMENDATION_DESCRIPTIONS[suggestion.recommendation] ?? suggestion.recommendation)
132-
: "N/A";
133-
const description = suggestion.description ?? "N/A";
134-
const triggeredBy = this.getTriggerDescriptions(suggestion);
135-
const affectedNamespaces = suggestion.affectedNamespaces?.length ?? 0;
136-
return `${i + 1} | ${recommendation} | ${description} | ${triggeredBy} | ${affectedNamespaces} namespaces`;
137-
})
138-
.join("\n");
139-
140-
return `# | Recommendation | Description | Triggered By | Affected Namespaces
141-
---|---------------|-------------|----------|-------------------
142-
${rows}`;
143-
}
144-
14535
protected async execute({
14636
projectId,
14737
clusterName,
@@ -213,7 +103,7 @@ ${rows}`;
213103
let totalItems = 0;
214104

215105
if (data.suggestedIndexes.length > 0) {
216-
const suggestedIndexesTable = this.formatSuggestedIndexesTable(data.suggestedIndexes);
106+
const suggestedIndexesTable = formatSuggestedIndexesTable(data.suggestedIndexes);
217107
formattedOutput += `\n## Suggested Indexes\n${suggestedIndexesTable}\n`;
218108
totalItems += data.suggestedIndexes.length;
219109
}
@@ -223,7 +113,7 @@ ${rows}`;
223113
data.dropIndexSuggestions.redundantIndexes.length > 0 ||
224114
data.dropIndexSuggestions.unusedIndexes.length > 0
225115
) {
226-
const dropIndexesTable = this.formatDropIndexesTable(data.dropIndexSuggestions);
116+
const dropIndexesTable = formatDropIndexesTable(data.dropIndexSuggestions);
227117
formattedOutput += `\n## Drop Index Suggestions\n${dropIndexesTable}\n`;
228118
totalItems +=
229119
data.dropIndexSuggestions.hiddenIndexes.length +
@@ -232,13 +122,13 @@ ${rows}`;
232122
}
233123

234124
if (data.slowQueryLogs.length > 0) {
235-
const slowQueriesTable = this.formatSlowQueriesTable(data.slowQueryLogs);
125+
const slowQueriesTable = formatSlowQueriesTable(data.slowQueryLogs);
236126
formattedOutput += `\n## Slow Query Logs\n${slowQueriesTable}\n`;
237127
totalItems += data.slowQueryLogs.length;
238128
}
239129

240130
if (data.schemaSuggestions.length > 0) {
241-
const schemaTable = this.formatSchemaSuggestionsTable(data.schemaSuggestions);
131+
const schemaTable = formatSchemaSuggestionsTable(data.schemaSuggestions);
242132
formattedOutput += `\n## Schema Suggestions\n${schemaTable}\n`;
243133
totalItems += data.schemaSuggestions.length;
244134
}

0 commit comments

Comments
 (0)