@appland/appmap 3.69.0 → 3.71.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/built/cmds/prune/prune.js +65 -7
- package/built/cmds/prune/prune.js.map +1 -1
- package/built/cmds/prune/pruneAppMap.js +14 -1
- package/built/cmds/prune/pruneAppMap.js.map +1 -1
- package/built/cmds/stats/directory/statsForDirectory.js +261 -0
- package/built/cmds/stats/directory/statsForDirectory.js.map +1 -0
- package/built/cmds/stats/directory/statsForMap.js +121 -0
- package/built/cmds/stats/directory/statsForMap.js.map +1 -0
- package/built/cmds/stats/stats.js +69 -247
- package/built/cmds/stats/stats.js.map +1 -1
- package/built/html/appmap.js +70 -70
- package/built/html/appmap.js.map +4 -4
- package/built/html/sequenceDiagram.js +70 -70
- package/built/html/sequenceDiagram.js.map +4 -4
- package/built/lib/handleWorkingDirectory.js +0 -1
- package/built/lib/handleWorkingDirectory.js.map +1 -1
- package/package.json +1 -1
|
@@ -4,273 +4,95 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.handler = exports.builder = exports.describe = exports.command = void 0;
|
|
7
|
-
const
|
|
8
|
-
const
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const glob_1 = __importDefault(require("glob"));
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const statsForDirectory_1 = require("./directory/statsForDirectory");
|
|
12
|
+
const statsForMap_1 = require("./directory/statsForMap");
|
|
13
|
+
const locateAppMapDir_1 = require("../../lib/locateAppMapDir");
|
|
9
14
|
const userInteraction_1 = __importDefault(require("../userInteraction"));
|
|
10
|
-
const telemetry_1 = __importDefault(require("../../telemetry"));
|
|
11
15
|
const utils_1 = require("../../utils");
|
|
12
|
-
const
|
|
13
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
14
|
-
const path_1 = require("path");
|
|
16
|
+
const handleWorkingDirectory_1 = require("../../lib/handleWorkingDirectory");
|
|
15
17
|
exports.command = 'stats [directory]';
|
|
16
|
-
exports.describe = 'Show
|
|
18
|
+
exports.describe = 'Show statistics about events from an AppMap or from all AppMaps in a directory';
|
|
17
19
|
const LIMIT_DEFAULT = 10;
|
|
18
|
-
|
|
20
|
+
async function locateAppMapFile(userInput, appmapDir) {
|
|
21
|
+
let extension = '.appmap.json';
|
|
22
|
+
if (userInput.endsWith('.appmap.json')) {
|
|
23
|
+
extension = '';
|
|
24
|
+
}
|
|
25
|
+
else if (userInput.endsWith('.appmap')) {
|
|
26
|
+
extension = '.json';
|
|
27
|
+
}
|
|
28
|
+
const globMatch = (globString) => {
|
|
29
|
+
return glob_1.default.sync(globString);
|
|
30
|
+
};
|
|
31
|
+
const appmapInWorkingDir = () => globMatch(path_1.default.join(appmapDir, '**', userInput + extension));
|
|
32
|
+
const appmapInAppMapDir = () => [path_1.default.join(userInput + extension)].filter((p) => (0, fs_1.existsSync)(p));
|
|
33
|
+
const appmapAbsolute = () => {
|
|
34
|
+
if (!path_1.default.isAbsolute(userInput + extension))
|
|
35
|
+
return [];
|
|
36
|
+
return globMatch(userInput + extension);
|
|
37
|
+
};
|
|
38
|
+
let matches = [...appmapAbsolute(), ...appmapInWorkingDir(), ...appmapInAppMapDir()];
|
|
39
|
+
if (matches.length === 0) {
|
|
40
|
+
console.error(chalk_1.default.red('No matching AppMap found'));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
else if (matches.length > 1) {
|
|
44
|
+
const { choice } = await userInteraction_1.default.prompt({
|
|
45
|
+
type: 'list',
|
|
46
|
+
choices: matches,
|
|
47
|
+
name: 'choice',
|
|
48
|
+
message: 'There are multiple matching AppMaps, which one do you want to anlyze?',
|
|
49
|
+
});
|
|
50
|
+
return choice;
|
|
51
|
+
}
|
|
52
|
+
return matches[0];
|
|
53
|
+
}
|
|
19
54
|
const builder = (args) => {
|
|
20
55
|
args.option('directory', {
|
|
21
|
-
describe: '
|
|
56
|
+
describe: 'program working directory',
|
|
22
57
|
type: 'string',
|
|
23
58
|
alias: 'd',
|
|
24
59
|
});
|
|
25
|
-
args.option('
|
|
26
|
-
describe: '
|
|
27
|
-
|
|
28
|
-
|
|
60
|
+
args.option('appmap-dir', {
|
|
61
|
+
describe: 'directory to recursively inspect for AppMaps',
|
|
62
|
+
});
|
|
63
|
+
args.option('format', {
|
|
64
|
+
describe: 'How to format the output',
|
|
65
|
+
choices: ['json', 'text'],
|
|
66
|
+
alias: 'f',
|
|
67
|
+
default: 'text',
|
|
29
68
|
});
|
|
30
69
|
args.option('limit', {
|
|
31
|
-
describe: '
|
|
70
|
+
describe: 'Number of methods to display',
|
|
32
71
|
type: 'number',
|
|
33
72
|
alias: 'l',
|
|
34
73
|
default: LIMIT_DEFAULT,
|
|
35
74
|
});
|
|
75
|
+
args.option('appmap-file', {
|
|
76
|
+
describe: 'AppMap to analyze',
|
|
77
|
+
type: 'string',
|
|
78
|
+
alias: 'a',
|
|
79
|
+
});
|
|
36
80
|
return args.strict();
|
|
37
81
|
};
|
|
38
82
|
exports.builder = builder;
|
|
39
83
|
async function handler(argv, handlerCaller = 'from_stats') {
|
|
40
84
|
(0, utils_1.verbose)(argv.verbose);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const appMapSizes = {};
|
|
53
|
-
// This function is too verbose to be useful in this context.
|
|
54
|
-
const v = (0, utils_1.verbose)();
|
|
55
|
-
(0, utils_1.verbose)(false);
|
|
56
|
-
await (0, utils_1.listAppMapFiles)(appMapDir, (fileName) => {
|
|
57
|
-
const stats = fs.statSync(fileName);
|
|
58
|
-
appMapSizes[fileName] = {
|
|
59
|
-
path: (0, path_1.relative)(appMapDir, fileName),
|
|
60
|
-
size: stats.size,
|
|
61
|
-
};
|
|
62
|
-
});
|
|
63
|
-
(0, utils_1.verbose)(v);
|
|
64
|
-
return appMapSizes;
|
|
65
|
-
}
|
|
66
|
-
async function sortAppMapSizes(appMapSizes) {
|
|
67
|
-
let appMapSizesArray = [];
|
|
68
|
-
for (const key in appMapSizes) {
|
|
69
|
-
appMapSizesArray.push({
|
|
70
|
-
path: appMapSizes[key].path,
|
|
71
|
-
size: appMapSizes[key].size,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
return appMapSizesArray.sort((a, b) => b.size - a.size);
|
|
75
|
-
}
|
|
76
|
-
function sizeInMB(size) {
|
|
77
|
-
return Number((size / 1000 / 1000).toFixed(1));
|
|
78
|
-
}
|
|
79
|
-
async function calculateExecutionTimes(appMapDir) {
|
|
80
|
-
// now that all functions were collected, index them by function
|
|
81
|
-
// name, not by <thread_id,parent_id>
|
|
82
|
-
let totalFunctionExecutionTimes = {};
|
|
83
|
-
// This function is too verbose to be useful in this context.
|
|
84
|
-
const v = (0, utils_1.verbose)();
|
|
85
|
-
(0, utils_1.verbose)(false);
|
|
86
|
-
// Note that event#elapsed time does NOT include instrumentation overhead.
|
|
87
|
-
// So, instrumentation / elapsed can theoretically be greater than 1.
|
|
88
|
-
let totalTime = 0;
|
|
89
|
-
await (0, utils_1.listAppMapFiles)(appMapDir, (fileName) => {
|
|
90
|
-
const file = fs.readFileSync(fileName, 'utf-8');
|
|
91
|
-
const appmapData = JSON.parse(file.toString());
|
|
92
|
-
const appmap = (0, models_1.buildAppMap)(appmapData).build();
|
|
93
|
-
appmap.events.forEach((event) => {
|
|
94
|
-
if (event.isCall()) {
|
|
95
|
-
const eventReturn = event.returnEvent;
|
|
96
|
-
if (!eventReturn)
|
|
97
|
-
return;
|
|
98
|
-
const name = event.codeObject.fqid;
|
|
99
|
-
let elapsedInstrumentationTime = eventReturn.elapsedInstrumentationTime || 0;
|
|
100
|
-
let path = '';
|
|
101
|
-
// some paths are library functions but don't start with /. i.e.:
|
|
102
|
-
// <internal:pack>
|
|
103
|
-
// OpenSSL::Cipher#decrypt
|
|
104
|
-
// Kernel#eval
|
|
105
|
-
if (event.definedClass &&
|
|
106
|
-
event.path &&
|
|
107
|
-
(event.path[0] == '/' ||
|
|
108
|
-
event.path[0] == '<' ||
|
|
109
|
-
event.path.includes('::') ||
|
|
110
|
-
event.path.startsWith('Kernel'))) {
|
|
111
|
-
// Absolute path names generally signify a library function.
|
|
112
|
-
// Send library function data to help optimize AppMap;
|
|
113
|
-
// don't send user function data.
|
|
114
|
-
path = event.path;
|
|
115
|
-
}
|
|
116
|
-
// Total up the elapsed time of root events.
|
|
117
|
-
if (!event.parent && eventReturn.elapsedTime) {
|
|
118
|
-
totalTime += eventReturn.elapsedTime;
|
|
119
|
-
}
|
|
120
|
-
const existingRecord = totalFunctionExecutionTimes[name];
|
|
121
|
-
if (!existingRecord) {
|
|
122
|
-
totalFunctionExecutionTimes[name] = {
|
|
123
|
-
path,
|
|
124
|
-
numberOfCalls: 1,
|
|
125
|
-
elapsedInstrumentationTime,
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
existingRecord.numberOfCalls += 1;
|
|
130
|
-
existingRecord.elapsedInstrumentationTime += elapsedInstrumentationTime;
|
|
131
|
-
if (existingRecord.path === '')
|
|
132
|
-
existingRecord.path = path;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
(0, utils_1.verbose)(v);
|
|
138
|
-
// convert hash to array
|
|
139
|
-
let flatFunctionExecutionTimes = [];
|
|
140
|
-
for (const name in totalFunctionExecutionTimes) {
|
|
141
|
-
flatFunctionExecutionTimes.push({
|
|
142
|
-
name: name,
|
|
143
|
-
elapsedInstrumentationTime: totalFunctionExecutionTimes[name].elapsedInstrumentationTime,
|
|
144
|
-
numberOfCalls: totalFunctionExecutionTimes[name].numberOfCalls,
|
|
145
|
-
path: totalFunctionExecutionTimes[name].path,
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
return { totalTime, functions: flatFunctionExecutionTimes };
|
|
149
|
-
}
|
|
150
|
-
async function sortExecutionTimes(functionExecutionTimes) {
|
|
151
|
-
// sort the array
|
|
152
|
-
return functionExecutionTimes.sort((a, b) => b.elapsedInstrumentationTime - a.elapsedInstrumentationTime);
|
|
153
|
-
}
|
|
154
|
-
async function showStats() {
|
|
155
|
-
let biggestAppMapSizes = [];
|
|
156
|
-
// column names in JSON files use snakecase
|
|
157
|
-
let slowestExecutionTimes = [];
|
|
158
|
-
try {
|
|
159
|
-
userInteraction_1.default.status = `Computing AppMap stats...`;
|
|
160
|
-
const appMapDir = directoryToUse;
|
|
161
|
-
const appMapSizes = await calculateAppMapSizes(appMapDir);
|
|
162
|
-
const sortedAppMapSizes = await sortAppMapSizes(appMapSizes);
|
|
163
|
-
userInteraction_1.default.success();
|
|
164
|
-
userInteraction_1.default.progress('');
|
|
165
|
-
userInteraction_1.default.progress(chalk_1.default.underline(`Largest AppMaps (which are bigger than ${MINIMUM_APPMAP_SIZE / 1024}kb)`));
|
|
166
|
-
sortedAppMapSizes
|
|
167
|
-
.filter((appmap) => appmap.size > MINIMUM_APPMAP_SIZE)
|
|
168
|
-
.slice(0, limitToUse)
|
|
169
|
-
.forEach((appmap) => {
|
|
170
|
-
biggestAppMapSizes.push({
|
|
171
|
-
size: appmap.size,
|
|
172
|
-
path: appmap.path,
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
if (json) {
|
|
176
|
-
console.log(JSON.stringify(biggestAppMapSizes));
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
biggestAppMapSizes.forEach((appmap) => {
|
|
180
|
-
console.log(sizeInMB(appmap.size) + 'MB ' + appmap.path);
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
userInteraction_1.default.progress('');
|
|
184
|
-
userInteraction_1.default.status = `Computing functions with highest AppMap overhead...`;
|
|
185
|
-
const executionTimes = await calculateExecutionTimes(appMapDir);
|
|
186
|
-
const sortedExecutionTimes = await sortExecutionTimes(executionTimes.functions);
|
|
187
|
-
let totalInstrumentationTime = 0;
|
|
188
|
-
sortedExecutionTimes.forEach((time) => (totalInstrumentationTime += time.elapsedInstrumentationTime));
|
|
189
|
-
userInteraction_1.default.success();
|
|
190
|
-
userInteraction_1.default.progress('');
|
|
191
|
-
// if there are no instrumentation data don't show this report
|
|
192
|
-
if (sortedExecutionTimes.length > 0 &&
|
|
193
|
-
sortedExecutionTimes[0].elapsedInstrumentationTime === 0) {
|
|
194
|
-
console.log("These AppMaps don't contain function overhead data. Please update your appmap package to the latest version.");
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
sortedExecutionTimes.slice(0, limitToUse).forEach((executionTime) => {
|
|
198
|
-
slowestExecutionTimes.push({
|
|
199
|
-
elapsed_instrumentation_time_total: Number(executionTime.elapsedInstrumentationTime.toFixed(6)),
|
|
200
|
-
num_calls: executionTime.numberOfCalls,
|
|
201
|
-
name: executionTime.name,
|
|
202
|
-
path: executionTime.path,
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
if (json) {
|
|
206
|
-
console.log(JSON.stringify(slowestExecutionTimes));
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
userInteraction_1.default.progress(chalk_1.default.underline(`Total instrumentation time`));
|
|
210
|
-
console.log(`${Math.round(totalInstrumentationTime * 1000)}ms`);
|
|
211
|
-
userInteraction_1.default.progress('');
|
|
212
|
-
userInteraction_1.default.progress(chalk_1.default.underline(`Functions with highest AppMap overhead`));
|
|
213
|
-
console.log(chalk_1.default.underline([
|
|
214
|
-
'Time'.padStart(9),
|
|
215
|
-
'%'.padStart(5),
|
|
216
|
-
'Count'.padStart(7),
|
|
217
|
-
'Function name'.padEnd(30),
|
|
218
|
-
].join(' | ')));
|
|
219
|
-
slowestExecutionTimes.forEach((executionTime) => {
|
|
220
|
-
const displayMs = [
|
|
221
|
-
Math.round(executionTime.elapsed_instrumentation_time_total * 1000).toString(),
|
|
222
|
-
'ms',
|
|
223
|
-
].join('');
|
|
224
|
-
const displayPercent = `${(Math.round((executionTime.elapsed_instrumentation_time_total / totalInstrumentationTime) *
|
|
225
|
-
1000) / 10).toLocaleString('en-us', { maximumFractionDigits: 2, minimumFractionDigits: 0 })}%`;
|
|
226
|
-
console.log([
|
|
227
|
-
displayMs.padStart(9),
|
|
228
|
-
displayPercent.padStart(5),
|
|
229
|
-
executionTime.num_calls.toString().padStart(7),
|
|
230
|
-
executionTime.name.split(':').slice(1).join(':'),
|
|
231
|
-
].join(' | '));
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
let telemetryMetrics = {};
|
|
236
|
-
let telemetryMetricsCounter = 1;
|
|
237
|
-
biggestAppMapSizes.forEach((appmap) => {
|
|
238
|
-
telemetryMetrics[`biggestAppmaps_${telemetryMetricsCounter}`] = appmap.size;
|
|
239
|
-
telemetryMetricsCounter += 1;
|
|
240
|
-
});
|
|
241
|
-
telemetryMetricsCounter = 1;
|
|
242
|
-
slowestExecutionTimes.forEach((executionTime) => {
|
|
243
|
-
telemetryMetrics[`slowestInstrumentationTimesTotal_${telemetryMetricsCounter}`] =
|
|
244
|
-
executionTime.elapsed_instrumentation_time_total;
|
|
245
|
-
telemetryMetrics[`slowestInstrumentationTimesPath_${telemetryMetricsCounter}`] =
|
|
246
|
-
executionTime.path;
|
|
247
|
-
telemetryMetricsCounter += 1;
|
|
248
|
-
});
|
|
249
|
-
telemetry_1.default.sendEvent({
|
|
250
|
-
name: `stats:${handlerCaller}:success`,
|
|
251
|
-
properties: {
|
|
252
|
-
path: appMapDir,
|
|
253
|
-
},
|
|
254
|
-
metrics: telemetryMetrics,
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
catch (err) {
|
|
258
|
-
let errorMessage = err.toString();
|
|
259
|
-
if (err instanceof Error) {
|
|
260
|
-
telemetry_1.default.sendEvent({
|
|
261
|
-
name: `stats:${handlerCaller}:error`,
|
|
262
|
-
properties: {
|
|
263
|
-
errorMessage,
|
|
264
|
-
errorStack: err.stack,
|
|
265
|
-
},
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
return [biggestAppMapSizes, slowestExecutionTimes];
|
|
270
|
-
}
|
|
271
|
-
return await showStats();
|
|
272
|
-
};
|
|
273
|
-
return await commandFn();
|
|
85
|
+
(0, handleWorkingDirectory_1.handleWorkingDirectory)(argv.directory);
|
|
86
|
+
const appmapDir = await (0, locateAppMapDir_1.locateAppMapDir)(argv.appmapDir);
|
|
87
|
+
const { format, limit, appmapFile } = argv;
|
|
88
|
+
if (appmapFile) {
|
|
89
|
+
const fileToAnalyze = await locateAppMapFile(appmapFile, appmapDir);
|
|
90
|
+
if (!fileToAnalyze)
|
|
91
|
+
return;
|
|
92
|
+
console.warn(`Analyzing AppMap: ${fileToAnalyze}`);
|
|
93
|
+
return await (0, statsForMap_1.statsForMap)(format, limit, fileToAnalyze);
|
|
94
|
+
}
|
|
95
|
+
return await (0, statsForDirectory_1.statsForDirectory)(appmapDir, format, limit, handlerCaller);
|
|
274
96
|
}
|
|
275
97
|
exports.handler = handler;
|
|
276
98
|
exports.default = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../../src/cmds/stats/stats.ts"],"names":[],"mappings":";;;;;;AACA,
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../../src/cmds/stats/stats.ts"],"names":[],"mappings":"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"}
|