UNPKG

visualise-elastic-profile

Version:

Visualise results from Profile API of ElasticSearch on the command line

89 lines 4.25 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.stringifyProfile = void 0; const chalk_1 = __importDefault(require("chalk")); const utils_1 = require("./utils"); /** * @param profileData JSON of the profilin data, checked against a runtype * @param options configuring the resulting string * @returns stringified represenentation of the profile */ const stringifyProfile = (profileData, options = { maxWidth: 80, color: true }) => { const result = []; let profile; if (utils_1.NestedProfile.guard(profileData)) { profile = utils_1.NestedProfile.check(profileData).profile; } else { profile = utils_1.Profile.check(profileData); } const maxTimeInNanos = profile.shards .flatMap((shard) => shard.searches) .flatMap((search) => search.query) .reduce((max, query) => Math.max(max, query.time_in_nanos), 0); // Determine colors to use per query type const queryTypes = (0, utils_1.getQueryTypesFromProfile)(profile); const colorByQueryType = options.color ? new Map(Array.from(queryTypes.values()).map((type, idx) => [type, (0, utils_1.getColor)(type)])) : undefined; const gray = options.color ? chalk_1.default.gray : (value) => value; const colorString = options.color ? (hex) => chalk_1.default.hex(hex) : (_) => (value) => value; // Write out a legend if the output is colored if (colorByQueryType !== undefined) { result.push(gray('Legend:')); for (const [type, color] of colorByQueryType) { result.push(`${colorString(color)('███')} - ${type}`); } result.push(''); } // Render each shard separately for (const shard of profile.shards) { result.push(`${gray('Shard:')} ${shard.id}`); const queries = shard.searches.flatMap((query) => query.query); for (const query of queries) { const relativeMaxWidth = Math.floor((query.time_in_nanos / maxTimeInNanos) * options.maxWidth); result.push((0, utils_1.queryToString)(query, { maxWidth: relativeMaxWidth, colorByQueryType })); } result.push(''); } // Render stats of the leaf queries (the ones that actually take up the time in the end) // Also render their breakdown aggregates over all shards result.push(gray('Leaf queries (across all shards/queries):')); const queries = (0, utils_1.getAllLeafQueriesFromProfile)(profile); const queriesByTypeDescription = (0, utils_1.arrayToMultiMap)(queries, ({ type, description }) => `${type} ${description}`); const durationsByDescription = Array.from(queriesByTypeDescription.values()) .map((queries) => { const sumTimeInNanos = queries.reduce((sum, query) => sum + query.time_in_nanos, 0); const breakdown = queries.reduce((memo, query) => { var _a; for (const [key, value] of Object.entries(query.breakdown)) { memo[key] = ((_a = memo[key]) !== null && _a !== void 0 ? _a : 0) + value; } return memo; }, {}); return { type: queries[0].type, description: queries[0].description, breakdown, color: colorByQueryType === null || colorByQueryType === void 0 ? void 0 : colorByQueryType.get(queries[0].type), time_in_nanos: sumTimeInNanos, }; }) .sort((a, b) => b.time_in_nanos - a.time_in_nanos); for (const value of durationsByDescription) { result.push(`${(0, utils_1.durationToString)(value.time_in_nanos)} - ${colorString(value.color)(`${value.type} ${value.description}`)}`); const breakdown = Array.from(Object.entries(value.breakdown)).sort((a, b) => b[1] - a[1]); for (const [key, aggregate] of breakdown) { if (aggregate > 0) { result.push(`\t${(0, utils_1.durationToString)(aggregate)} ${gray(key)}`); } } result.push(''); } return result.join('\n'); }; exports.stringifyProfile = stringifyProfile; //# sourceMappingURL=index.js.map