@appland/appmap 3.28.1 → 3.29.2
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 +27 -0
- package/built/appmap.html +1 -1
- package/built/cmds/open/showAppMap.js +10 -17
- package/built/cmds/open/showAppMap.js.map +1 -1
- package/built/depends.js +37 -20
- package/built/depends.js.map +1 -1
- package/built/fingerprint/appmapIndex.js +156 -0
- package/built/fingerprint/appmapIndex.js.map +1 -0
- package/built/fingerprint/fingerprintQueue.js +8 -1
- package/built/fingerprint/fingerprintQueue.js.map +1 -1
- package/built/fingerprint/fingerprinter.js +41 -100
- package/built/fingerprint/fingerprinter.js.map +1 -1
- package/built/main.js.map +1 -1
- package/built/search/findEvents.js +9 -1
- package/built/search/findEvents.js.map +1 -1
- package/built/telemetry.js +1 -2
- package/built/telemetry.js.map +1 -1
- package/built/utils.js +36 -31
- package/built/utils.js.map +1 -1
- package/package.json +4 -5
|
@@ -15,26 +15,19 @@ const Openers = [
|
|
|
15
15
|
];
|
|
16
16
|
async function showAppMap(appMapFile) {
|
|
17
17
|
const termProgram = process.env.TERM_PROGRAM;
|
|
18
|
-
if (process.platform === 'darwin') {
|
|
19
|
-
|
|
20
|
-
(0, child_process_1.spawn)('code', [(0, openers_1.abspath)(appMapFile)]);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
18
|
+
if (process.platform === 'darwin' && termProgram === 'vscode') {
|
|
19
|
+
(0, child_process_1.spawn)('code', [(0, openers_1.abspath)(appMapFile)]);
|
|
23
20
|
}
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
else {
|
|
22
|
+
await (0, openers_1.openInBrowser)(appMapFile);
|
|
23
|
+
}
|
|
24
|
+
const { action } = await userInteraction_1.default.prompt({
|
|
26
25
|
type: 'list',
|
|
27
|
-
name: '
|
|
28
|
-
message: '
|
|
29
|
-
choices:
|
|
26
|
+
name: 'action',
|
|
27
|
+
message: 'What would you like to do next:',
|
|
28
|
+
choices: [`Reopen ${appMapFile}`, 'Exit']
|
|
30
29
|
});
|
|
31
|
-
|
|
32
|
-
if (opener) {
|
|
33
|
-
console.log();
|
|
34
|
-
console.log(`Click this link to open the AppMap in ${outputTool}:`);
|
|
35
|
-
console.log();
|
|
36
|
-
await opener.fn(appMapFile, opener.toolId);
|
|
37
|
-
console.log();
|
|
30
|
+
if (action.startsWith('Reopen')) {
|
|
38
31
|
await showAppMap(appMapFile);
|
|
39
32
|
}
|
|
40
33
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"showAppMap.js","sourceRoot":"","sources":["../../../src/cmds/open/showAppMap.ts"],"names":[],"mappings":";;;;;AAAA,iDAAsC;AACtC,yEAAoC;AACpC,uCAA6E;AAQ7E,MAAM,OAAO,GAAa;IACxB,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,uBAAa,EAAE;IAC1C,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,sBAAY,EAAE;IACrC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,oBAAU,EAAE;IACpD,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,oBAAU,EAAE;IACtD,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,oBAAU,EAAE;CACvD,CAAC;AAEa,KAAK,UAAU,UAAU,CAAC,UAAkB;IACzD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IAC7C,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,
|
|
1
|
+
{"version":3,"file":"showAppMap.js","sourceRoot":"","sources":["../../../src/cmds/open/showAppMap.ts"],"names":[],"mappings":";;;;;AAAA,iDAAsC;AACtC,yEAAoC;AACpC,uCAA6E;AAQ7E,MAAM,OAAO,GAAa;IACxB,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,uBAAa,EAAE;IAC1C,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,sBAAY,EAAE;IACrC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,oBAAU,EAAE;IACpD,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,oBAAU,EAAE;IACtD,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,oBAAU,EAAE;CACvD,CAAC;AAEa,KAAK,UAAU,UAAU,CAAC,UAAkB;IACzD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IAC7C,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,WAAW,KAAK,QAAQ,EAAE;QAC7D,IAAA,qBAAK,EAAC,MAAM,EAAE,CAAC,IAAA,iBAAO,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC;KACtC;SACI;QACH,MAAM,IAAA,uBAAa,EAAC,UAAU,CAAC,CAAC;KACjC;IAED,MAAM,EAAC,MAAM,EAAC,GAAG,MAAM,yBAAE,CAAC,MAAM,CAAC;QAC/B,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,iCAAiC;QAC1C,OAAO,EAAE,CAAC,UAAU,UAAU,EAAE,EAAE,MAAM,CAAC;KAC1C,CAAC,CAAC;IACH,IAAI,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;QAC/B,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC;KAC9B;AACH,CAAC;AAlBD,6BAkBC"}
|
package/built/depends.js
CHANGED
|
@@ -46,7 +46,7 @@ class Depends {
|
|
|
46
46
|
* @param {string} filePath
|
|
47
47
|
* @returns string
|
|
48
48
|
*/
|
|
49
|
-
|
|
49
|
+
makeAbsolutePath(filePath) {
|
|
50
50
|
if (isAbsolute(filePath)) {
|
|
51
51
|
return filePath;
|
|
52
52
|
}
|
|
@@ -62,23 +62,23 @@ class Depends {
|
|
|
62
62
|
*/
|
|
63
63
|
async depends(callback) {
|
|
64
64
|
const outOfDateNames = new Set();
|
|
65
|
-
async
|
|
65
|
+
const checkClassMap = async (fileName) => {
|
|
66
66
|
const indexDir = dirname(fileName);
|
|
67
67
|
if (basename(indexDir) === 'Inventory') {
|
|
68
68
|
return;
|
|
69
69
|
}
|
|
70
|
-
let
|
|
70
|
+
let appmapUpdatedAtStr;
|
|
71
71
|
try {
|
|
72
|
-
|
|
72
|
+
appmapUpdatedAtStr = await fsp.readFile(joinPath(indexDir, 'mtime'));
|
|
73
73
|
}
|
|
74
74
|
catch (err) {
|
|
75
75
|
if (err.code !== 'ENOENT')
|
|
76
76
|
console.warn(err);
|
|
77
77
|
return;
|
|
78
78
|
}
|
|
79
|
-
const
|
|
79
|
+
const appmapUpdatedAt = parseFloat(appmapUpdatedAtStr);
|
|
80
80
|
if (verbose()) {
|
|
81
|
-
console.
|
|
81
|
+
console.log(`Checking AppMap ${indexDir} with timestamp ${appmapUpdatedAt}`);
|
|
82
82
|
}
|
|
83
83
|
const classMap = JSON.parse(await fsp.readFile(fileName));
|
|
84
84
|
const codeLocations = new Set();
|
|
@@ -92,31 +92,40 @@ class Depends {
|
|
|
92
92
|
}
|
|
93
93
|
};
|
|
94
94
|
classMap.forEach(collectFilePaths);
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
async function checkTimestamps(filePath) {
|
|
99
|
-
const dependencyFilePath = this.applyBaseDir(filePath);
|
|
95
|
+
const isClientProvidedFile = (filePath) => this.testLocations.has(filePath);
|
|
96
|
+
const isFileModifiedSince = async (filePath) => {
|
|
97
|
+
const dependencyFilePath = this.makeAbsolutePath(filePath);
|
|
100
98
|
const dependencyModifiedAt = await mtime(dependencyFilePath);
|
|
99
|
+
// TODO: Actually, if the dependency file does not exist, we should return true.
|
|
100
|
+
// However, at this time we can't tell the difference between a dependency file that has
|
|
101
|
+
// been deleted, and one that never existed in the first place. What does 'never existed in the first place'
|
|
102
|
+
// mean? Well, unfortunately the Ruby agent (and perhaps others?) will write file locations
|
|
103
|
+
// like 'JSON' for native functions that don't actually correspond to real files.
|
|
104
|
+
if (!dependencyModifiedAt) {
|
|
105
|
+
if (verbose())
|
|
106
|
+
console.log(`[depends] ${dependencyFilePath} does not exist`);
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
const uptodate = appmapUpdatedAt < dependencyModifiedAt;
|
|
101
110
|
if (verbose()) {
|
|
102
|
-
console.
|
|
111
|
+
console.log(`[depends] ${dependencyFilePath} timestamp is ${dependencyModifiedAt}, ${uptodate ? 'up to date' : 'NOT up to date'} with ${indexDir} (${appmapUpdatedAt})`);
|
|
103
112
|
}
|
|
104
|
-
return
|
|
105
|
-
}
|
|
113
|
+
return uptodate;
|
|
114
|
+
};
|
|
106
115
|
if (this.testLocations && verbose()) {
|
|
107
|
-
console.
|
|
116
|
+
console.log(`Checking whether AppMap contains any client-provided file: [ ${[
|
|
108
117
|
...this.testLocations,
|
|
109
118
|
]
|
|
110
119
|
.sort()
|
|
111
120
|
.join(', ')} ]`);
|
|
112
121
|
}
|
|
113
122
|
const testFunction = this.testLocations
|
|
114
|
-
?
|
|
115
|
-
:
|
|
123
|
+
? isClientProvidedFile
|
|
124
|
+
: isFileModifiedSince;
|
|
116
125
|
await Promise.all([...codeLocations].map(async (filePath) => {
|
|
117
126
|
if (await testFunction(filePath)) {
|
|
118
127
|
if (verbose()) {
|
|
119
|
-
console.
|
|
128
|
+
console.log(`${filePath} requires rebuild of AppMap ${indexDir}`);
|
|
120
129
|
}
|
|
121
130
|
if (!outOfDateNames.has(indexDir)) {
|
|
122
131
|
if (callback) {
|
|
@@ -126,8 +135,16 @@ class Depends {
|
|
|
126
135
|
}
|
|
127
136
|
}
|
|
128
137
|
}));
|
|
129
|
-
}
|
|
130
|
-
await processFiles(`${this.appMapDir}/**/classMap.json`,
|
|
138
|
+
};
|
|
139
|
+
await processFiles(`${this.appMapDir}/**/classMap.json`, async (fileName) => {
|
|
140
|
+
try {
|
|
141
|
+
await checkClassMap(fileName);
|
|
142
|
+
}
|
|
143
|
+
catch (e) {
|
|
144
|
+
console.log(e.code);
|
|
145
|
+
console.warn(`Error checking uptodate ${fileName}: ${e}`);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
131
148
|
return [...outOfDateNames].sort();
|
|
132
149
|
}
|
|
133
150
|
}
|
package/built/depends.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"depends.js","sourceRoot":"","sources":["../src/depends.js"],"names":[],"mappings":";AAAA,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC;AACnC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAC1E,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAE5D,qFAAqF;AACrF,gCAAgC;AAChC,MAAM,aAAa,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAE3D,MAAM,OAAO;IACX;;OAEG;IACH,YAAY,SAAS;QACnB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;IACrB,CAAC;IAED;;;;;;;;OAQG;IACH,IAAI,OAAO,CAAC,OAAO;QACjB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC1B,CAAC;IAED;;;;;;;OAOG;IACH,IAAI,KAAK,CAAC,KAAK;QACb,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACzB,6CAA6C;YAC7C,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC;SACjB;QACD,IAAI,CAAC,aAAa,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC;IAED;;;;;OAKG;IACH,
|
|
1
|
+
{"version":3,"file":"depends.js","sourceRoot":"","sources":["../src/depends.js"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const assert_1 = __importDefault(require("assert"));
|
|
7
|
+
const promises_1 = require("fs/promises");
|
|
8
|
+
const path_1 = require("path");
|
|
9
|
+
const semver_1 = require("semver");
|
|
10
|
+
const utils_1 = require("../utils");
|
|
11
|
+
/**
|
|
12
|
+
* Raw AppMaps are processed into an index, which consists of:
|
|
13
|
+
*
|
|
14
|
+
* * `the-appmap.appmap.json` Canonicalized AppMap file (replaces the original AppMap).
|
|
15
|
+
* * `the-appmap/version` Identifies the index algorithm version.
|
|
16
|
+
* * `the-appmap/classMap.json` 'classMap' object extracted from the AppMap.
|
|
17
|
+
* * `the-appmap/metadata.json` 'metadata' object extracted from the AppMap.
|
|
18
|
+
* * `the-appmap/mtime` Time at which the AppMap was indexed.
|
|
19
|
+
*
|
|
20
|
+
* Other optional fields may be present as well.
|
|
21
|
+
*/
|
|
22
|
+
class AppMapIndex {
|
|
23
|
+
/**
|
|
24
|
+
* Constructs a new AppMapIndex. After calling the constructor, call `initialize`.
|
|
25
|
+
*
|
|
26
|
+
* @param appmapFileName The path to the AppMap file.
|
|
27
|
+
* @see initialize
|
|
28
|
+
*/
|
|
29
|
+
constructor(appmapFileName) {
|
|
30
|
+
this.appmapFileName = appmapFileName;
|
|
31
|
+
this.indexDir = (0, utils_1.baseName)(appmapFileName);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Performs async operations needed to initialize the index. If this method returns false,
|
|
35
|
+
* abort.
|
|
36
|
+
*/
|
|
37
|
+
async initialize() {
|
|
38
|
+
const appmapCreatedAt = await (0, utils_1.mtime)(this.appmapFileName);
|
|
39
|
+
if (!appmapCreatedAt) {
|
|
40
|
+
console.log(`File ${this.appmapFileName} does not exist or is not a file.`);
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
this.appmapCreatedAt = appmapCreatedAt;
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Creates the index directory that will contain the processed files.
|
|
48
|
+
*/
|
|
49
|
+
async mkdir_p() {
|
|
50
|
+
await (0, promises_1.mkdir)(this.indexDir, { recursive: true });
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Creates a data file within the index directory.
|
|
54
|
+
*
|
|
55
|
+
* @param fileName The name of the file to write within the index directory.
|
|
56
|
+
* @param data Raw data to store.
|
|
57
|
+
*/
|
|
58
|
+
async writeFileAtomic(fileName, data) {
|
|
59
|
+
await (0, utils_1.writeFileAtomic)(this.indexDir, fileName, this.appmapCreatedAt, data);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Loads the raw AppMap data that will be indexed.
|
|
63
|
+
*
|
|
64
|
+
* @returns the raw data of the AppMap file.
|
|
65
|
+
*/
|
|
66
|
+
async loadAppMapData() {
|
|
67
|
+
let appmapStr;
|
|
68
|
+
try {
|
|
69
|
+
appmapStr = await (0, promises_1.readFile)(this.appmapFileName, 'utf-8');
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
if (e.code === 'ENOENT') {
|
|
73
|
+
console.log(`${this.appmapFileName} does not exist.`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
throw e;
|
|
77
|
+
}
|
|
78
|
+
if ((0, utils_1.verbose)()) {
|
|
79
|
+
console.log(`Read ${appmapStr.length} bytes from ${this.appmapFileName}`);
|
|
80
|
+
}
|
|
81
|
+
let appmapData;
|
|
82
|
+
try {
|
|
83
|
+
appmapData = JSON.parse(appmapStr);
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
if (err instanceof SyntaxError) {
|
|
87
|
+
// File may be in the process of writing.
|
|
88
|
+
console.warn(`Error parsing JSON file ${this.appmapFileName} : ${err.message}`);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
throw err;
|
|
92
|
+
}
|
|
93
|
+
if (!appmapData.metadata) {
|
|
94
|
+
if ((0, utils_1.verbose)()) {
|
|
95
|
+
console.warn(`${this.appmapFileName} has no metadata. Skipping...`);
|
|
96
|
+
}
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
return appmapData;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* @returns number of bytes in the AppMap.
|
|
103
|
+
*/
|
|
104
|
+
async appmapFileSize() {
|
|
105
|
+
return (await (0, promises_1.stat)(this.appmapFileName)).size;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Tests whether the existing index is using the current algorithm.
|
|
109
|
+
*
|
|
110
|
+
* @param requiredVersion The current version of the index algorithm.
|
|
111
|
+
*/
|
|
112
|
+
async versionUpToDate(requiredVersion) {
|
|
113
|
+
const versionFileName = (0, path_1.join)(this.indexDir, 'version');
|
|
114
|
+
let versionStr;
|
|
115
|
+
try {
|
|
116
|
+
versionStr = await (0, promises_1.readFile)(versionFileName, 'utf-8');
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
if (err.code !== 'ENOENT') {
|
|
120
|
+
throw err;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (!versionStr)
|
|
124
|
+
return false;
|
|
125
|
+
versionStr = versionStr.trim();
|
|
126
|
+
if ((0, utils_1.verbose)()) {
|
|
127
|
+
console.log(`${this.indexDir} index version is ${versionStr}`);
|
|
128
|
+
}
|
|
129
|
+
return (0, semver_1.satisfies)(versionStr, `>= ${requiredVersion}`);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Tests whether the existing index is up to date with the raw AppMap data.
|
|
133
|
+
*/
|
|
134
|
+
async indexUpToDate() {
|
|
135
|
+
(0, assert_1.default)(this.appmapCreatedAt, `AppMap index is not initialized`);
|
|
136
|
+
const mtimeFileName = (0, path_1.join)(this.indexDir, 'mtime');
|
|
137
|
+
let indexedAtStr;
|
|
138
|
+
try {
|
|
139
|
+
indexedAtStr = await (0, promises_1.readFile)(mtimeFileName, 'utf-8');
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
if (err.code !== 'ENOENT') {
|
|
143
|
+
throw err;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (!indexedAtStr)
|
|
147
|
+
return false;
|
|
148
|
+
const indexedAt = parseFloat(indexedAtStr);
|
|
149
|
+
if ((0, utils_1.verbose)()) {
|
|
150
|
+
console.log(`${this.indexDir} created at ${this.appmapCreatedAt}, indexed at ${indexedAt}`);
|
|
151
|
+
}
|
|
152
|
+
return indexedAt >= this.appmapCreatedAt;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
exports.default = AppMapIndex;
|
|
156
|
+
//# sourceMappingURL=appmapIndex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"appmapIndex.js","sourceRoot":"","sources":["../../src/fingerprint/appmapIndex.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,14 @@ class FingerprintQueue {
|
|
|
7
7
|
this.size = size;
|
|
8
8
|
// eslint-disable-next-line no-use-before-define
|
|
9
9
|
this.handler = new Fingerprinter(printCanonicalAppMaps);
|
|
10
|
-
this.queue = queue(
|
|
10
|
+
this.queue = queue(async (appmapFileName) => {
|
|
11
|
+
try {
|
|
12
|
+
await this.handler.fingerprint(appmapFileName);
|
|
13
|
+
}
|
|
14
|
+
catch (e) {
|
|
15
|
+
console.warn(`Error fingerprinting ${appmapFileName}: ${e}`);
|
|
16
|
+
}
|
|
17
|
+
}, this.size);
|
|
11
18
|
this.queue.pause();
|
|
12
19
|
}
|
|
13
20
|
setCounterFn(counterFn) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fingerprintQueue.js","sourceRoot":"","sources":["../../src/fingerprint/fingerprintQueue.js"],"names":[],"mappings":";AAAA,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AACnC,MAAM,EAAE,OAAO,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;AACtE,MAAM,aAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAEjD,MAAM,gBAAgB;IACpB,YAAY,IAAI,GAAG,CAAC,EAAE,qBAAqB,GAAG,IAAI;QAChD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,gDAAgD;QAChD,IAAI,CAAC,OAAO,GAAG,IAAI,aAAa,CAAC,qBAAqB,CAAC,CAAC;QACxD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"fingerprintQueue.js","sourceRoot":"","sources":["../../src/fingerprint/fingerprintQueue.js"],"names":[],"mappings":";AAAA,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AACnC,MAAM,EAAE,OAAO,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;AACtE,MAAM,aAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAEjD,MAAM,gBAAgB;IACpB,YAAY,IAAI,GAAG,CAAC,EAAE,qBAAqB,GAAG,IAAI;QAChD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,gDAAgD;QAChD,IAAI,CAAC,OAAO,GAAG,IAAI,aAAa,CAAC,qBAAqB,CAAC,CAAC;QACxD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE;YAC1C,IAAI;gBACF,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;aAChD;YAAC,OAAO,CAAC,EAAE;gBACV,OAAO,CAAC,IAAI,CAAC,wBAAwB,cAAc,KAAK,CAAC,EAAE,CAAC,CAAC;aAC9D;QACH,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,YAAY,CAAC,SAAS;QACpB,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,OAAO;QACX,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBACzB,IAAI,KAAK,YAAY,iBAAiB,EAAE;oBACtC,OAAO,CAAC,IAAI,CACV;wBACE,YAAY,KAAK,CAAC,OAAO,EAAE;wBAC3B,yFAAyF;qBAC1F,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;iBACH;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE;oBAClC,OAAO,CAAC,IAAI,CAAC,YAAY,KAAK,CAAC,IAAI,4BAA4B,CAAC,CAAC;iBAClE;;oBAAM,MAAM,CAAC,KAAK,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,GAAG;QACN,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;CACF;AAED,MAAM,CAAC,OAAO,GAAG,gBAAgB,CAAC"}
|
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const { createHash } = require('crypto');
|
|
3
|
-
const { join: joinPath } = require('path');
|
|
3
|
+
const { join: joinPath, basename } = require('path');
|
|
4
4
|
const fsp = require('fs').promises;
|
|
5
|
-
const semver = require('semver');
|
|
6
5
|
const { buildAppMap } = require('@appland/models');
|
|
7
|
-
const
|
|
6
|
+
const assert = require('assert');
|
|
8
7
|
const { default: FileTooLargeError } = require('./fileTooLargeError');
|
|
9
|
-
const { verbose,
|
|
8
|
+
const { verbose, mtime } = require('../utils');
|
|
10
9
|
const { algorithms, canonicalize } = require('./canonicalize');
|
|
10
|
+
const { default: AppMapIndex } = require('./appmapIndex');
|
|
11
11
|
/**
|
|
12
12
|
* CHANGELOG
|
|
13
13
|
*
|
|
14
|
+
* # 1.1.3
|
|
15
|
+
*
|
|
16
|
+
* * Removed ctime file. Use mtime to determine when the AppMap was last updated.
|
|
17
|
+
* * Use higher precision for mtime.
|
|
18
|
+
*
|
|
14
19
|
* # 1.1.2
|
|
15
20
|
*
|
|
16
|
-
* * Reject large appmaps
|
|
21
|
+
* * Reject large appmaps to avoid running out of system resources trying to process them.
|
|
17
22
|
*
|
|
18
23
|
* # 1.1.1
|
|
19
24
|
*
|
|
@@ -26,7 +31,7 @@ const { algorithms, canonicalize } = require('./canonicalize');
|
|
|
26
31
|
* * Fix handling of parent assignment in normalization.
|
|
27
32
|
* * sql can contain the analysis (action, tables, columns), and/or the normalized query string.
|
|
28
33
|
*/
|
|
29
|
-
const VERSION = '1.1.
|
|
34
|
+
const VERSION = '1.1.3';
|
|
30
35
|
const MAX_APPMAP_SIZE = 50 * 1000 * 1000;
|
|
31
36
|
class Fingerprinter {
|
|
32
37
|
/**
|
|
@@ -41,93 +46,28 @@ class Fingerprinter {
|
|
|
41
46
|
}
|
|
42
47
|
// eslint-disable-next-line class-methods-use-this
|
|
43
48
|
async fingerprint(appMapFileName) {
|
|
44
|
-
const appMapCreatedAt = await ctime(appMapFileName, false);
|
|
45
|
-
if (!appMapCreatedAt) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
49
|
if (verbose()) {
|
|
49
|
-
console.
|
|
50
|
+
console.log(`Fingerprinting ${appMapFileName}`);
|
|
50
51
|
}
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
const versionFileName = joinPath(indexDir, 'version');
|
|
54
|
-
const versionUpToDate = async () => {
|
|
55
|
-
let versionStr = '0.0.1';
|
|
56
|
-
try {
|
|
57
|
-
versionStr = await fsp.readFile(versionFileName);
|
|
58
|
-
}
|
|
59
|
-
catch (err) {
|
|
60
|
-
if (err.code !== 'ENOENT') {
|
|
61
|
-
throw err;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
versionStr = versionStr.toString().trim();
|
|
65
|
-
if (verbose()) {
|
|
66
|
-
console.warn(`${appMapFileName} index version is ${versionStr}`);
|
|
67
|
-
}
|
|
68
|
-
return semver.satisfies(versionStr, `>= ${VERSION}`);
|
|
69
|
-
};
|
|
70
|
-
const indexUpToDate = async () => {
|
|
71
|
-
let indexedAt = 0;
|
|
72
|
-
try {
|
|
73
|
-
const indexedAtStr = await fsp.readFile(mtimeFileName);
|
|
74
|
-
indexedAt = parseInt(indexedAtStr, 10);
|
|
75
|
-
}
|
|
76
|
-
catch (err) {
|
|
77
|
-
if (err.code !== 'ENOENT') {
|
|
78
|
-
throw err;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
if (verbose()) {
|
|
82
|
-
console.warn(`${appMapFileName} created at ${appMapCreatedAt}, indexed at ${indexedAt}`);
|
|
83
|
-
}
|
|
84
|
-
return indexedAt >= appMapCreatedAt;
|
|
85
|
-
};
|
|
86
|
-
if ((await versionUpToDate()) && (await indexUpToDate())) {
|
|
87
|
-
if (verbose()) {
|
|
88
|
-
console.warn('Fingerprint is up to date. Skipping...');
|
|
89
|
-
}
|
|
52
|
+
const index = new AppMapIndex(appMapFileName);
|
|
53
|
+
if (!(await index.initialize())) {
|
|
90
54
|
return;
|
|
91
55
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (stat.size > MAX_APPMAP_SIZE)
|
|
95
|
-
throw new FileTooLargeError(appMapFileName, stat.size, MAX_APPMAP_SIZE);
|
|
96
|
-
}
|
|
97
|
-
let data;
|
|
98
|
-
try {
|
|
99
|
-
data = await fsp.readFile(appMapFileName);
|
|
100
|
-
}
|
|
101
|
-
catch (e) {
|
|
102
|
-
if (e.code !== 'ENOENT') {
|
|
103
|
-
console.warn(`${appMapFileName} does not exist. Skipping...`);
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
throw e;
|
|
107
|
-
}
|
|
108
|
-
if (verbose()) {
|
|
109
|
-
console.warn(`Read ${data.length} bytes`);
|
|
110
|
-
}
|
|
111
|
-
let appmapData;
|
|
112
|
-
try {
|
|
113
|
-
// TODO: Should we normalize, compress, etc here?
|
|
114
|
-
appmapData = JSON.parse(data.toString());
|
|
115
|
-
}
|
|
116
|
-
catch (err) {
|
|
117
|
-
if (err instanceof SyntaxError) {
|
|
118
|
-
// File may be in the process of writing.
|
|
119
|
-
console.warn(`Error parsing JSON file ${appMapFileName} : ${err.message}`);
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
throw err;
|
|
123
|
-
}
|
|
124
|
-
if (!appmapData.metadata) {
|
|
56
|
+
if ((await index.versionUpToDate(VERSION)) &&
|
|
57
|
+
(await index.indexUpToDate())) {
|
|
125
58
|
if (verbose()) {
|
|
126
|
-
console.
|
|
59
|
+
console.log('Fingerprint is up to date. Skipping...');
|
|
127
60
|
}
|
|
128
61
|
return;
|
|
129
62
|
}
|
|
130
|
-
|
|
63
|
+
if ((await index.appmapFileSize()) > MAX_APPMAP_SIZE)
|
|
64
|
+
throw new FileTooLargeError(appMapFileName, await index.appmapFileSize(), MAX_APPMAP_SIZE);
|
|
65
|
+
const appmapData = await index.loadAppMapData();
|
|
66
|
+
if (!appmapData)
|
|
67
|
+
return;
|
|
68
|
+
const appmapDataWithoutMetadata = await index.loadAppMapData();
|
|
69
|
+
if (!appmapDataWithoutMetadata)
|
|
70
|
+
return;
|
|
131
71
|
delete appmapDataWithoutMetadata.metadata;
|
|
132
72
|
const appmapDigest = createHash('sha256')
|
|
133
73
|
.update(JSON.stringify(appmapDataWithoutMetadata, null, 2))
|
|
@@ -135,19 +75,16 @@ class Fingerprinter {
|
|
|
135
75
|
const fingerprints = [];
|
|
136
76
|
appmapData.metadata.fingerprints = fingerprints;
|
|
137
77
|
const appmap = buildAppMap(appmapData).normalize().build();
|
|
138
|
-
await
|
|
78
|
+
await index.mkdir_p();
|
|
139
79
|
await Promise.all(Object.keys(algorithms).map(async (algorithmName) => {
|
|
140
80
|
const canonicalForm = canonicalize(algorithmName, appmap);
|
|
141
81
|
const canonicalJSON = JSON.stringify(canonicalForm, null, 2);
|
|
142
82
|
if (this.printCanonicalAppMaps) {
|
|
143
|
-
await writeFileAtomic(
|
|
83
|
+
await index.writeFileAtomic(`canonical.${algorithmName}.json`, canonicalJSON);
|
|
144
84
|
}
|
|
145
85
|
const fingerprintDigest = createHash('sha256')
|
|
146
86
|
.update(canonicalJSON)
|
|
147
87
|
.digest('hex');
|
|
148
|
-
if (verbose()) {
|
|
149
|
-
console.warn(`Computed digest for ${algorithmName}`);
|
|
150
|
-
}
|
|
151
88
|
fingerprints.push({
|
|
152
89
|
appmap_digest: appmapDigest,
|
|
153
90
|
canonicalization_algorithm: algorithmName,
|
|
@@ -156,16 +93,20 @@ class Fingerprinter {
|
|
|
156
93
|
});
|
|
157
94
|
}));
|
|
158
95
|
appmapData.metadata.fingerprints.sort((a, b) => a.canonicalization_algorithm.localeCompare(b.canonicalization_algorithm));
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
await
|
|
162
|
-
|
|
163
|
-
await
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
96
|
+
const tempAppMapFileName = joinPath(index.indexDir, 'appmap.tmp');
|
|
97
|
+
await index.writeFileAtomic(basename(tempAppMapFileName), JSON.stringify(appmap, null, 2));
|
|
98
|
+
const appMapIndexedAt = await mtime(tempAppMapFileName);
|
|
99
|
+
assert(appMapIndexedAt, `${tempAppMapFileName} should always exist and be a readable file`);
|
|
100
|
+
await Promise.all([
|
|
101
|
+
index.writeFileAtomic('version', VERSION),
|
|
102
|
+
index.writeFileAtomic('classMap.json', JSON.stringify(appmap.classMap, null, 2)),
|
|
103
|
+
index.writeFileAtomic('metadata.json', JSON.stringify(appmap.metadata, null, 2)),
|
|
104
|
+
index.writeFileAtomic('mtime', `${appMapIndexedAt}`),
|
|
105
|
+
]);
|
|
106
|
+
// At this point, moving the AppMap file into place will trigger re-indexing.
|
|
107
|
+
// But the mtime will match the file modification time, so the algorithm will
|
|
108
|
+
// determine that the index is up-to-date.
|
|
109
|
+
await fsp.rename(tempAppMapFileName, appMapFileName, { overwrite: true });
|
|
169
110
|
this.counterFn();
|
|
170
111
|
}
|
|
171
112
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fingerprinter.js","sourceRoot":"","sources":["../../src/fingerprint/fingerprinter.js"],"names":[],"mappings":";AAAA,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AACzC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"fingerprinter.js","sourceRoot":"","sources":["../../src/fingerprint/fingerprinter.js"],"names":[],"mappings":"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"}
|