@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
JavaScript
;
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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