UNPKG

@oaklean/cli

Version:

A command-line interface that provides utilities for parsing, inspecting, and converting the .oak file format, as well as interfaces used in the @oaklean suite.

280 lines 24.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const fs = __importStar(require("fs")); const profiler_core_1 = require("@oaklean/profiler-core"); const commander_1 = require("commander"); class ReportCommands { constructor() { const baseCommand = commander_1.program .command('report') .description("commands to convert or inspect the profiler's format"); baseCommand .command('toHash') .description('Calculates the hash of given a profiler format') .argument('<input>', 'input file path') .action(this.toHash.bind(this)); baseCommand .command('toJSON') .description('Converts a profiler format that is given in binary format to a json version') .argument('<input>', 'input file path') .argument('<output>', 'output file path') .action(this.convertToJSON.bind(this)); baseCommand .command('toSourceFileTree') .description('Converts a profiler format that is given in binary format to a SourceFileMetaDataTree') .argument('<input>', 'input file path') .argument('<output>', 'output file path') .action(this.convertToSourceFileMetaDataTreeTree.bind(this)); baseCommand .command('check') .description('Checks wether all files in the profiler format are present') .option('--sn, --source-nodes', 'Specifies if source nodes should also be checked', false) .argument('<input>', 'input file path') .action(this.check.bind(this)); baseCommand .command('inspect') .description('Displays an overview of the reports stats') .argument('<input>', 'input file path') .option('--lm, --list-modules', 'Displays a list of node modules', false) .action(this.inspect.bind(this)); } static init() { return new ReportCommands(); } toHash(input) { return __awaiter(this, void 0, void 0, function* () { let inputPath = new profiler_core_1.UnifiedPath(input); if (inputPath.isRelative()) { inputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(inputPath); } const report = profiler_core_1.ProjectReport.loadFromFile(inputPath, 'bin'); if (report === undefined) { profiler_core_1.LoggerHelper.error(`Could not find a profiler report at ${inputPath.toPlatformString()}`); return; } profiler_core_1.LoggerHelper.log(`Hash: ${report.hash()}`); }); } convertToJSON(input, output) { return __awaiter(this, void 0, void 0, function* () { let inputPath = new profiler_core_1.UnifiedPath(input); if (inputPath.isRelative()) { inputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(inputPath); } let outputPath = new profiler_core_1.UnifiedPath(output); if (outputPath.isRelative()) { outputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(outputPath); } const report = profiler_core_1.ProjectReport.loadFromFile(inputPath, 'bin'); if (report === undefined) { profiler_core_1.LoggerHelper.error(`Could not find a profiler report at ${inputPath.toPlatformString()}`); return; } report.storeToFile(outputPath, 'pretty-json'); }); } convertToSourceFileMetaDataTreeTree(input, output) { return __awaiter(this, void 0, void 0, function* () { let inputPath = new profiler_core_1.UnifiedPath(input); if (inputPath.isRelative()) { inputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(inputPath); } let outputPath = new profiler_core_1.UnifiedPath(output); if (outputPath.isRelative()) { outputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(outputPath); } const report = profiler_core_1.ProjectReport.loadFromFile(inputPath, 'bin'); if (report === undefined) { profiler_core_1.LoggerHelper.error(`Could not find a profiler report at ${inputPath.toPlatformString()}`); return; } const tree = profiler_core_1.SourceFileMetaDataTree.fromProjectReport(report).filter(report.asSourceNodeGraph(), undefined, undefined).node; if (tree === null) { profiler_core_1.LoggerHelper.error('Could not create SourceFileMetaDataTree'); return; } tree.storeToFile(outputPath, 'pretty-json'); }); } check(input, options) { return __awaiter(this, void 0, void 0, function* () { var _a; let inputPath = new profiler_core_1.UnifiedPath(input); if (inputPath.isRelative()) { inputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(inputPath); } const report = profiler_core_1.ProjectReport.loadFromFile(inputPath, 'bin'); if (report === undefined) { profiler_core_1.LoggerHelper.error(`Could not find a profiler report at ${inputPath.toPlatformString()}`); return; } const reversePathMap = (_a = report.globalIndex.getModuleIndex('get')) === null || _a === void 0 ? void 0 : _a.reversePathMap; if (reversePathMap === undefined) { profiler_core_1.LoggerHelper.error('Could not find reversePathMap'); return; } const pstPerFile = new Map(); for (const pathIndex of reversePathMap.values()) { if (!fs.existsSync(new profiler_core_1.UnifiedPath(pathIndex.identifier).toPlatformString())) { profiler_core_1.LoggerHelper.error(`Could not find file ${pathIndex.identifier}`); continue; } if (options.sourceNodes) { let pst = pstPerFile.get(pathIndex.identifier); if (pst === undefined) { pst = profiler_core_1.TypescriptParser.parseFile(new profiler_core_1.UnifiedPath(pathIndex.identifier)); pstPerFile.set(pathIndex.identifier, pst); } const notFoundSourceNodes = []; for (const sourceNodeIndex of pathIndex.reverseSourceNodeMap.values()) { if (sourceNodeIndex.presentInOriginalSourceCode) { if (pst.sourceLocationOfIdentifier(sourceNodeIndex.identifier) === null) { notFoundSourceNodes.push(sourceNodeIndex.identifier); } } } if (notFoundSourceNodes.length > 0) { profiler_core_1.LoggerHelper.error(`Could not find source nodes in file ${pathIndex.identifier}`); profiler_core_1.LoggerHelper.table(notFoundSourceNodes); } } } const nodeModulePath = new profiler_core_1.UnifiedPath(process.cwd()).join('node_modules'); for (const [nodeModuleIdentifier, moduleIndex] of report.globalIndex.moduleMap.entries()) { if (nodeModuleIdentifier === '{self}' || nodeModuleIdentifier === '{node}') { continue; } const nodeModule = profiler_core_1.NodeModule.fromIdentifier(nodeModuleIdentifier); if (nodeModule.isWasmModule()) { continue; } for (const pathIndex of moduleIndex.reversePathMap.values()) { const relativeNodeModulePath = new profiler_core_1.UnifiedPath(nodeModule.name).join(pathIndex.identifier); const filePath = nodeModulePath .join(relativeNodeModulePath) .toPlatformString(); if (!fs.existsSync(filePath)) { profiler_core_1.LoggerHelper.error(`Could not find file ${relativeNodeModulePath}`); } } } }); } inspect(input, options) { return __awaiter(this, void 0, void 0, function* () { let inputPath = new profiler_core_1.UnifiedPath(input); if (inputPath.isRelative()) { inputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(inputPath); } const report = profiler_core_1.ProjectReport.loadFromFile(inputPath, 'bin'); if (report === undefined) { profiler_core_1.LoggerHelper.error(`Could not find a profiler report at ${inputPath.toPlatformString()}`); return; } const node_modules = []; for (const key of report.globalIndex.moduleMap.keys()) { if (key === '{self}' || key === '{node}') { continue; } node_modules.push(key); } const total = report.totalAndMaxMetaData().total; profiler_core_1.LoggerHelper.table([ { type: 'Node modules count', value: node_modules.length } ], ['type', 'value', 'unit']); profiler_core_1.LoggerHelper.table([ { category: 'headless', description: 'Headless measurements have no parent, so they originate from node internal operations like timers, events, etc.' }, { category: 'non-headless', description: 'Non-headless measurements have a parent, so they originate from user code.' }, { category: 'total', description: 'Total measurements are the sum of headless and non-headless measurements, so the total consumption of the process.' } ], ['category', 'description']); profiler_core_1.LoggerHelper.table([ { type: 'cpu time', headless: report.headlessSensorValues.selfCPUTime, 'non-headless': total.sensorValues.aggregatedCPUTime - report.headlessSensorValues.selfCPUTime, total: total.sensorValues.aggregatedCPUTime, unit: 'µs' }, { type: 'cpu energy', headless: report.headlessSensorValues.selfCPUEnergyConsumption, 'non-headless': total.sensorValues.aggregatedCPUEnergyConsumption - report.headlessSensorValues.selfCPUEnergyConsumption, total: total.sensorValues.aggregatedCPUEnergyConsumption, unit: 'mJ' }, { type: 'ram energy', headless: report.headlessSensorValues.selfRAMEnergyConsumption, 'non-headless': total.sensorValues.aggregatedRAMEnergyConsumption - report.headlessSensorValues.selfRAMEnergyConsumption, total: total.sensorValues.aggregatedRAMEnergyConsumption, unit: 'mJ' } ], ['type', 'headless', 'non-headless', 'total', 'unit']); if (options.listModules) { profiler_core_1.LoggerHelper.log('Node modules:'); profiler_core_1.LoggerHelper.table(node_modules); } }); } } exports.default = ReportCommands; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUmVwb3J0Q29tbWFuZHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvUmVwb3J0Q29tbWFuZHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSx1Q0FBd0I7QUFFeEIsMERBVStCO0FBQy9CLHlDQUFtQztBQUVuQyxNQUFxQixjQUFjO0lBQ2xDO1FBQ0MsTUFBTSxXQUFXLEdBQUcsbUJBQU87YUFDekIsT0FBTyxDQUFDLFFBQVEsQ0FBQzthQUNqQixXQUFXLENBQUMsc0RBQXNELENBQUMsQ0FBQTtRQUVyRSxXQUFXO2FBQ1QsT0FBTyxDQUFDLFFBQVEsQ0FBQzthQUNqQixXQUFXLENBQUMsZ0RBQWdELENBQUM7YUFDN0QsUUFBUSxDQUFDLFNBQVMsRUFBRSxpQkFBaUIsQ0FBQzthQUN0QyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtRQUVoQyxXQUFXO2FBQ1QsT0FBTyxDQUFDLFFBQVEsQ0FBQzthQUNqQixXQUFXLENBQ1gsNkVBQTZFLENBQzdFO2FBQ0EsUUFBUSxDQUFDLFNBQVMsRUFBRSxpQkFBaUIsQ0FBQzthQUN0QyxRQUFRLENBQUMsVUFBVSxFQUFFLGtCQUFrQixDQUFDO2FBQ3hDLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFBO1FBRXZDLFdBQVc7YUFDVCxPQUFPLENBQUMsa0JBQWtCLENBQUM7YUFDM0IsV0FBVyxDQUNYLHVGQUF1RixDQUN2RjthQUNBLFFBQVEsQ0FBQyxTQUFTLEVBQUUsaUJBQWlCLENBQUM7YUFDdEMsUUFBUSxDQUFDLFVBQVUsRUFBRSxrQkFBa0IsQ0FBQzthQUN4QyxNQUFNLENBQUMsSUFBSSxDQUFDLG1DQUFtQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxD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