meminsight-test-demo 1.0.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.
Files changed (76) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +36 -0
  3. package/docs/Build.md +68 -0
  4. package/docs/Interface.md +35 -0
  5. package/docs/UserGuide.md +332 -0
  6. package/docs/resources/analyzer.png +0 -0
  7. package/docs/resources/cfg_filter_filetype_json.png +0 -0
  8. package/docs/resources/filetype_txt.png +0 -0
  9. package/docs/resources/framework.png +0 -0
  10. package/docs/resources/output.png +0 -0
  11. package/docs/resources/process.png +0 -0
  12. package/package.json +54 -0
  13. package/packages/cfg/ArkStatCfg.json +33 -0
  14. package/packages/core/jest.config.js +8 -0
  15. package/packages/core/package.json +61 -0
  16. package/packages/core/src/Index.ts +53 -0
  17. package/packages/core/src/analyzer/AnalysisInfo.ts +298 -0
  18. package/packages/core/src/analyzer/ArkAnalyzer.ts +42 -0
  19. package/packages/core/src/analyzer/ArkCmpCfg.ts +22 -0
  20. package/packages/core/src/analyzer/ArkCompareAnalyzer.ts +173 -0
  21. package/packages/core/src/analyzer/ArkLeakAnalyzer.ts +196 -0
  22. package/packages/core/src/analyzer/ArkSerializer.ts +163 -0
  23. package/packages/core/src/analyzer/ArkStatAnalyzer.ts +191 -0
  24. package/packages/core/src/analyzer/ArkStatCfg.ts +77 -0
  25. package/packages/core/src/analyzer/ArkTracePath.ts +269 -0
  26. package/packages/core/src/analyzer/ArkTracer.ts +42 -0
  27. package/packages/core/src/analyzer/ArkXAnalyzer.ts +631 -0
  28. package/packages/core/src/analyzer/IAnalyzer.ts +27 -0
  29. package/packages/core/src/file/FileReader.ts +82 -0
  30. package/packages/core/src/file/FileService.ts +50 -0
  31. package/packages/core/src/file/FileWriter.ts +148 -0
  32. package/packages/core/src/report/Reporter.ts +81 -0
  33. package/packages/core/src/report/templates/template.ejs +101 -0
  34. package/packages/core/src/report/templates/template.ts +103 -0
  35. package/packages/core/src/shell/DeviceShell.ts +179 -0
  36. package/packages/core/src/shell/Shell.ts +99 -0
  37. package/packages/core/src/types/Constants.ts +16 -0
  38. package/packages/core/src/types/LeakTypes.ts +21 -0
  39. package/packages/core/src/types/OhosTypes.ts +115 -0
  40. package/packages/core/src/utils/Common.ts +37 -0
  41. package/packages/core/src/utils/Finder.ts +390 -0
  42. package/packages/core/src/utils/Loader.ts +53 -0
  43. package/packages/core/src/utils/Log.ts +252 -0
  44. package/packages/core/src/utils/Output.ts +271 -0
  45. package/packages/core/tsconfig.json +10 -0
  46. package/packages/exampletools/package.json +52 -0
  47. package/packages/exampletools/src/MemTest.ts +64 -0
  48. package/packages/exampletools/tsconfig.json +15 -0
  49. package/packages/meminsight/jest.config.js +8 -0
  50. package/packages/meminsight/package.json +52 -0
  51. package/packages/meminsight/src/Index.ts +4 -0
  52. package/packages/meminsight/src/Version.ts +7 -0
  53. package/packages/meminsight/src/process/ArkCompareProc.ts +160 -0
  54. package/packages/meminsight/src/process/ArkGCProc.ts +61 -0
  55. package/packages/meminsight/src/process/ArkLeakProc.ts +47 -0
  56. package/packages/meminsight/src/process/ArkStatProc.ts +320 -0
  57. package/packages/meminsight/src/process/ArkXProc.ts +73 -0
  58. package/packages/meminsight/src/process/HMemXProc.ts +50 -0
  59. package/packages/meminsight/src/process/IProcess.ts +12 -0
  60. package/packages/meminsight/tsconfig.json +15 -0
  61. package/packages/stack/README.md +31 -0
  62. package/packages/stack/libs/hstack_lib-1.0.0.tgz +0 -0
  63. package/packages/stack/libs/hstack_lib-1.0.1.tgz +0 -0
  64. package/packages/stack/libs/hstack_lib-1.0.4.tgz +0 -0
  65. package/packages/stack/libs/lib_list.json +34 -0
  66. package/packages/stack/package.json +27 -0
  67. package/packages/stack/src/Index.js +29 -0
  68. package/packages/stack/src/StackTracer.js +53 -0
  69. package/packages/templates/ArkLeaks.template +9 -0
  70. package/packages/templates/ArkNodes.template +9 -0
  71. package/packages/templates/ArkPaths.template +9 -0
  72. package/test/scripts/merge.py +145 -0
  73. package/test/scripts/stat.py +175 -0
  74. package/test/test_ark_stat_proc.sh +14 -0
  75. package/tsconfig.base.json +38 -0
  76. package/tsconfig.json +8 -0
@@ -0,0 +1,271 @@
1
+
2
+ import { TextWriter, JsonWriter, HtmlWriter } from '../file/FileWriter';
3
+ import { ILoggable, Log } from './Log';
4
+
5
+ /**
6
+ * output type
7
+ */
8
+ export enum OutputType {
9
+ CONSOLE = 'console',
10
+ TEXT = 'txt',
11
+ JSON = 'json',
12
+ HTML = 'html'
13
+ }
14
+
15
+ /**
16
+ * output config
17
+ */
18
+ export type OutputCfg = {
19
+ desc: any;
20
+ output: {
21
+ dir: string;
22
+ filename: string;
23
+ extension: string;
24
+ }
25
+ node?: {
26
+ enableId: boolean,
27
+ enableType: boolean,
28
+ enableName: boolean,
29
+ enableSelfSize: boolean,
30
+ enableRetainedSize: boolean
31
+ }
32
+ }
33
+
34
+ /**
35
+ * output interface
36
+ */
37
+ export interface IOutput {
38
+ type: OutputType;
39
+ output(data: any, cfg: OutputCfg): void;
40
+ }
41
+
42
+ /**
43
+ * console data
44
+ */
45
+ export class ConsoleData {
46
+ table: boolean;
47
+ data: any;
48
+
49
+ constructor(table: boolean, data: any) {
50
+ this.table = table;
51
+ this.data = data;
52
+ }
53
+ }
54
+
55
+ /**
56
+ * console table data
57
+ */
58
+ export class ConsoleTableData {
59
+ title: string[];
60
+ data: any[];
61
+
62
+ constructor(title: string[], data: any[]) {
63
+ this.title = title;
64
+ this.data = data;
65
+ }
66
+ }
67
+
68
+ /**
69
+ * text data
70
+ */
71
+ export class TextData {
72
+ desc: any;
73
+ data: any;
74
+
75
+ constructor(desc: any, data: any) {
76
+ this.desc = desc;
77
+ this.data = data;
78
+ }
79
+ }
80
+
81
+ /**
82
+ * json data
83
+ */
84
+ export class JsonData {
85
+ desc: any;
86
+ data: any;
87
+
88
+ constructor(desc: any, data: any) {
89
+ this.desc = desc;
90
+ this.data = data;
91
+ }
92
+ }
93
+
94
+ /**
95
+ * html data
96
+ */
97
+ export class HtmlData {
98
+ desc: any;
99
+ data: any;
100
+ template: string;
101
+ delimiter: string;
102
+
103
+ constructor(desc: any, data: any, template?: string) {
104
+ this.desc = desc;
105
+ this.data = data;
106
+ this.template = template || '';
107
+ this.delimiter = 'DATA=';
108
+ }
109
+ }
110
+
111
+ /**
112
+ * base output
113
+ */
114
+ abstract class BaseOutput implements IOutput, ILoggable {
115
+ public readonly type: OutputType;
116
+ public readonly DOMAIN: string = 'meminsight';
117
+ public readonly TAG: string;
118
+
119
+ constructor(type: OutputType) {
120
+ this.type = type;
121
+ this.TAG = type.toString();
122
+ }
123
+
124
+ public output(data: any, cfg?: OutputCfg): void {}
125
+
126
+ protected getFilePathByCfg(cfg?: OutputCfg) : string {
127
+ if (cfg && cfg.output.filename != '') {
128
+ return `${cfg.output.dir}/${cfg.output.filename}.${cfg.output.extension}`;
129
+ } else {
130
+ let dir = './output';
131
+ let filename = `output_${Date.now()}`;
132
+ let extension = this.type.toString();
133
+ return `${dir}/${filename}.${extension}`;
134
+ }
135
+ }
136
+ }
137
+
138
+ /**
139
+ * console output
140
+ */
141
+ export class ConsoleOutput extends BaseOutput {
142
+ constructor() {
143
+ super(OutputType.CONSOLE);
144
+ }
145
+
146
+ public output(data: any, cfg?: OutputCfg): void {
147
+ const consoleData = data as ConsoleData;
148
+ if (consoleData) {
149
+ if (cfg?.desc) {
150
+ console.log(cfg?.desc);
151
+ }
152
+ if (consoleData.table) {
153
+ const tableData = consoleData.data as ConsoleTableData;
154
+ console.table(tableData.data, tableData.title);
155
+ } else {
156
+ console.log(consoleData.data);
157
+ }
158
+ } else {
159
+ if (typeof data === 'string') {
160
+ console.log(data);
161
+ } else {
162
+ Log.errorX(this, 'No data to output');
163
+ }
164
+ }
165
+ }
166
+ }
167
+
168
+ /**
169
+ * text output
170
+ */
171
+ export class TextOutput extends BaseOutput {
172
+ constructor() {
173
+ super(OutputType.TEXT);
174
+ }
175
+
176
+ public output(data: any, cfg?: OutputCfg): void {
177
+ let filePath = this.getFilePathByCfg(cfg);
178
+ let textData = data as TextData;
179
+ if (textData) {
180
+ const tmpData = {
181
+ 'meta': cfg?.desc,
182
+ 'data': textData,
183
+ }
184
+ TextWriter.instance().writeToFile(filePath, JSON.stringify(tmpData), 'utf-8');
185
+ } else {
186
+ if (typeof data === 'string') {
187
+ TextWriter.instance().writeToFile(filePath, data, 'utf-8');
188
+ } else {
189
+ Log.errorX(this, 'No data to output');
190
+ }
191
+ }
192
+ }
193
+ }
194
+
195
+ /**
196
+ * json output
197
+ */
198
+ export class JsonOutput extends BaseOutput {
199
+ constructor() {
200
+ super(OutputType.JSON);
201
+ }
202
+
203
+ public output(data: any, cfg?: OutputCfg): void {
204
+ let filePath = this.getFilePathByCfg(cfg);
205
+ let jsonData = data as JsonData;
206
+ if (jsonData) {
207
+ const tmpData = {
208
+ 'meta': jsonData.desc,
209
+ 'data': jsonData.data
210
+ }
211
+ JsonWriter.instance().writeToFile(filePath, tmpData, 'utf-8');
212
+ } else {
213
+ if (typeof data === 'string') {
214
+ JsonWriter.instance().writeToFile(filePath, data, 'utf-8');
215
+ } else {
216
+ Log.errorX(this, 'No data to output');
217
+ }
218
+ }
219
+ }
220
+ }
221
+
222
+ /**
223
+ * html output
224
+ */
225
+ export class HtmlOutput extends BaseOutput {
226
+ constructor() {
227
+ super(OutputType.HTML);
228
+ }
229
+
230
+ public output(data: any, cfg?: OutputCfg): void {
231
+ let filePath = this.getFilePathByCfg(cfg);
232
+ let htmlData = data as HtmlData;
233
+ if (htmlData) {
234
+ const tmpData = {
235
+ 'meta': cfg?.desc,
236
+ 'data': htmlData,
237
+ }
238
+ HtmlWriter.instance().writeToFile(filePath, JSON.stringify(tmpData), 'utf-8');
239
+ } else {
240
+ if (typeof data === 'string') {
241
+ HtmlWriter.instance().writeToFile(filePath, data, 'utf-8');
242
+ } else {
243
+ Log.errorX(this, 'No data to output');
244
+ }
245
+ }
246
+ }
247
+ }
248
+
249
+ /**
250
+ * output factory
251
+ */
252
+ export class OutputFactory {
253
+ private static _defaultOutput: IOutput = new ConsoleOutput();
254
+ private static OUTPUT_MAP: Map<string, IOutput> = new Map(
255
+ [
256
+ [OutputType.CONSOLE.toString(), OutputFactory._defaultOutput],
257
+ [OutputType.HTML.toString(), new HtmlOutput()],
258
+ [OutputType.JSON.toString(), new JsonOutput()],
259
+ [OutputType.TEXT.toString(), new TextOutput()],
260
+ ]
261
+ );
262
+
263
+
264
+ public static getOutput(type: string): IOutput {
265
+ let output = OutputFactory.OUTPUT_MAP.get(type);
266
+ if (!output) {
267
+ return OutputFactory._defaultOutput;
268
+ }
269
+ return output;
270
+ }
271
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src",
6
+ },
7
+ "include": [
8
+ "./src/**/*"
9
+ ]
10
+ }
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@meminsight/example-tools",
3
+ "version": "1.0.0",
4
+ "description": "example-tools for memory analysis.",
5
+ "author": {
6
+ "name": "meminsight-example-tools"
7
+ },
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "test": "jest",
11
+ "publish": "npm publish",
12
+ "clean": "rm -rf ./dist && rm -rf ./tsconfig.tsbuildinfo",
13
+ "clean-all": "rm -rf ./dist && rm -rf ./tsconfig.tsbuildinfo && rm -rf ./node_modules && find ./src -type f -name \"*.js\" -exec rm -f {} +"
14
+ },
15
+ "main": "dist/MemTest.js",
16
+ "bin": "dist/MemTest.js",
17
+ "engines": {
18
+ "node": ">=16.0.0"
19
+ },
20
+ "dependencies": {
21
+ "@memlab/core": "^1.0.40",
22
+ "@memlab/heap-analysis": "^1.0.40",
23
+ "@types/node": "^22.14.1",
24
+ "@types/jest": "^29.1.1",
25
+ "@types/ejs": "^3.1.5",
26
+ "ejs": "^3.1.10",
27
+ "axios": "^1.1.3",
28
+ "ansi": "^0.3.1",
29
+ "fs-extra": "^11.2.0",
30
+ "string-width": "^7.2.0",
31
+ "babar": "^0.2.0",
32
+ "chalk": "^5.4.1",
33
+ "minimist": "^1.2.8",
34
+ "util.promisify": "^1.1.1",
35
+ "node-xlsx": "^0.24.0",
36
+ "jest": "^29.1.1",
37
+ "typescript": "^5.3.3"
38
+ },
39
+ "devDependencies": {
40
+ "@types/fs-extra": "^11.0.4",
41
+ "@types/node": "^22.14.1",
42
+ "@types/minimist": "^1.2.2",
43
+ "@types/jest": "^29.1.1",
44
+ "jest": "^29.7.0",
45
+ "ts-jest": "^29.1.1",
46
+ "ts-node": "^10.9.1",
47
+ "typescript": "^5.3.3"
48
+ },
49
+ "workspaces": [
50
+ "../packages/core"
51
+ ]
52
+ }
@@ -0,0 +1,64 @@
1
+ import {
2
+ OutputFactory, OutputCfg, OutputType,
3
+ Finder, Loader,
4
+ ArkSerializer, ArkNodeTracePath,
5
+ Log
6
+ } from '@meminsight/core';
7
+
8
+ const DOMAIN: string = 'exampletools';
9
+ const TAG: string = 'memtest';
10
+
11
+ const args = process.argv.slice();
12
+ const type = args.length > 2 ? Number(args[2]) : 0;
13
+ const count = args.length > 3 ? Number(args[3]) : 5;
14
+ const nodeName = args.length > 4 ? args[4] : '';
15
+ const filepath = args.length > 5 ? args[5] : '';
16
+
17
+ function error(msg: string) {
18
+ Log.error(DOMAIN, TAG, msg);
19
+ }
20
+
21
+ function info(msg: string) {
22
+ Log.info(DOMAIN, TAG, msg);
23
+ }
24
+
25
+ (async function () {
26
+ if (filepath === '') {
27
+ error('filepath is empty.');
28
+ return;
29
+ }
30
+ const snapshot = await Loader.loadFromFile(filepath);
31
+
32
+ if (type === 0) {
33
+ const nodes = Finder.findNodesByNameCount(snapshot, nodeName, count);
34
+ const cfg: OutputCfg = {
35
+ desc: '',
36
+ output: {
37
+ dir: '',
38
+ filename: '',
39
+ extension: OutputType.CONSOLE.toString(),
40
+ },
41
+ node: {
42
+ enableId: true,
43
+ enableType: true,
44
+ enableName: true,
45
+ enableSelfSize: false,
46
+ enableRetainedSize: false,
47
+ }
48
+ };
49
+ let nodeData = ArkSerializer.getConsoleDataByNodes(true, nodes, cfg);
50
+ OutputFactory.getOutput(OutputType.CONSOLE).output(nodeData, cfg);
51
+ } else {
52
+ const nodes = Finder.findNodesByNameCount(snapshot, nodeName, count);
53
+ const shortestPaths = Finder.findShortestPaths(snapshot, nodes);
54
+ let set = new Set<number>();
55
+ shortestPaths.forEach(item => {
56
+ if (item) {
57
+ let tracePath = new ArkNodeTracePath(item, true);
58
+ let pathStr = tracePath.getTracePathInfo();
59
+ console.log(pathStr);
60
+ console.log('\n');
61
+ }
62
+ });
63
+ }
64
+ })();
@@ -0,0 +1,15 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src",
6
+ },
7
+ "include": [
8
+ "src/**/*"
9
+ ],
10
+ "references": [
11
+ {
12
+ "path": "../core"
13
+ }
14
+ ]
15
+ }
@@ -0,0 +1,8 @@
1
+ /** @type {import('ts-jest').JestConfigWithTsJest} **/
2
+ module.exports = {
3
+ preset: 'ts-jest',
4
+ testEnvironment: 'node',
5
+ transform: {
6
+ '^.+\\.ts?$': 'ts-jest',
7
+ },
8
+ };
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@meminsight/cmd",
3
+ "version": "1.0.0",
4
+ "description": "meminsight binary is a command tool for memory analysis.",
5
+ "author": {
6
+ "name": "meminsight-cmd"
7
+ },
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "test": "jest",
11
+ "publish": "npm publish",
12
+ "clean": "rm -rf ./dist && rm -rf ./tsconfig.tsbuildinfo",
13
+ "clean-all": "rm -rf ./dist && rm -rf ./tsconfig.tsbuildinfo && rm -rf ./node_modules && find ./src -type f -name \"*.js\" -exec rm -f {} +"
14
+ },
15
+ "main": "dist/Index.js",
16
+ "bin": "dist/Index.js",
17
+ "engines": {
18
+ "node": ">=16.0.0"
19
+ },
20
+ "dependencies": {
21
+ "@memlab/core": "^1.0.40",
22
+ "@memlab/heap-analysis": "^1.0.40",
23
+ "@types/node": "^22.14.1",
24
+ "@types/jest": "^29.1.1",
25
+ "@types/ejs": "^3.1.5",
26
+ "ejs": "^3.1.10",
27
+ "axios": "^1.1.3",
28
+ "ansi": "^0.3.1",
29
+ "fs-extra": "^11.2.0",
30
+ "string-width": "^7.2.0",
31
+ "babar": "^0.2.0",
32
+ "chalk": "^5.4.1",
33
+ "minimist": "^1.2.8",
34
+ "util.promisify": "^1.1.1",
35
+ "node-xlsx": "^0.24.0",
36
+ "jest": "^29.1.1",
37
+ "typescript": "^5.3.3"
38
+ },
39
+ "devDependencies": {
40
+ "@types/fs-extra": "^11.0.4",
41
+ "@types/node": "^22.14.1",
42
+ "@types/minimist": "^1.2.2",
43
+ "@types/jest": "^29.1.1",
44
+ "jest": "^29.7.0",
45
+ "ts-jest": "^29.1.1",
46
+ "ts-node": "^10.9.1",
47
+ "typescript": "^5.3.3"
48
+ },
49
+ "workspaces": [
50
+ "../packages/core"
51
+ ]
52
+ }
@@ -0,0 +1,4 @@
1
+
2
+ import { meminsight as cmdtools } from './process/HMemXProc';
3
+
4
+ cmdtools.work();
@@ -0,0 +1,7 @@
1
+ export enum Version {
2
+ HMEMX = '0.0.1',
3
+ ARK_GC = '0.0.1',
4
+ ARK_STAT = '0.0.1',
5
+ ARK_LEAK = '0.0.1',
6
+ ARK_COMPARE = '0.0.1'
7
+ }
@@ -0,0 +1,160 @@
1
+ import { Command } from "commander";
2
+ import {
3
+ ILoggable, Log,
4
+ IAnalyzer, ArkCompareAnalyzer, ArkCmpCfg, defaultArkCmpCfg,
5
+ IOutput, OutputCfg, OutputFactory, OutputType,
6
+ JsonReader,
7
+ ConsoleData,
8
+ JsonData,
9
+ TextData,
10
+ HtmlData
11
+ } from "@meminsight/core";
12
+ import { IProcess } from "./IProcess";
13
+ import { Version } from "../Version";
14
+ import { outputFile } from "fs-extra";
15
+
16
+ /**
17
+ * Ark Compare Process
18
+ */
19
+ export class ArkCompareProc implements IProcess, ILoggable {
20
+ public readonly DOMAIN: string = 'meminsight';
21
+ public readonly TAG: string = ArkCompareProc.name;
22
+ public static readonly CMD: string = 'ark-compare';
23
+ public static readonly DESC: string = "ark compare process.";
24
+ public static readonly VER: string = Version.ARK_COMPARE.toString();
25
+ private static _instance: ArkCompareProc;
26
+ private _analyzer: IAnalyzer = new ArkCompareAnalyzer();
27
+
28
+ private constructor() {}
29
+
30
+ /**
31
+ * get instance
32
+ * @returns instance
33
+ */
34
+ public static instance(): ArkCompareProc {
35
+ if (!ArkCompareProc._instance) {
36
+ ArkCompareProc._instance = new ArkCompareProc();
37
+ }
38
+ return ArkCompareProc._instance;
39
+ }
40
+
41
+ public initialize(proc: Command, any: any) {
42
+ proc.command(ArkCompareProc.CMD)
43
+ .description(ArkCompareProc.DESC)
44
+ .requiredOption("-s, --source <file>", "source heapsnapshot file")
45
+ .requiredOption("-t, --target <file>", "target heapsnapshot file")
46
+ .option("-n, --node_name <node name>", undefined)
47
+ .option<number>("-S, --sort_type <sort type: 0 - count | 1 - self_size | 2 - retained_size>", "sort type", parseInt, 0)
48
+ .option("-c, --config <configuration file>", "configuration file")
49
+ .option("-o, --output <file>", "output file")
50
+ .option("-f, --output_file <file type>", "output file type, console | text | json | html.")
51
+ .action(async (options) => {
52
+ await ArkCompareProc.instance().process(new Map<string, any>([
53
+ ["source", options.source],
54
+ ["target", options.target || undefined],
55
+ ["node_name", options.node_name || undefined],
56
+ ["sort_type", options.sort_type || "count"],
57
+ ["config", options.config || undefined],
58
+ ["output", options.output],
59
+ ["output_file", options.output_file],
60
+ ]));
61
+ });
62
+ }
63
+
64
+ private async process(args: Map<string, any>): Promise<void> {
65
+ let source = args.get("source");
66
+ if (!source) {
67
+ Log.errorX(this, "Source filepath is required");
68
+ return;
69
+ }
70
+ let target = args.get("target");
71
+ if (!target) {
72
+ Log.errorX(this, "Target filepath is required");
73
+ return;
74
+ }
75
+ let result = await this._analyzer.analyze([source, target]);
76
+ if (!result) {
77
+ Log.errorX(this, "Faled to analyze.");
78
+ return
79
+ }
80
+ Log.infoX(this, "Analyzed successfully.");
81
+
82
+ let cfgfile = args.get('config');
83
+ let setResult: boolean = false;
84
+ if (cfgfile) {
85
+ let cfg = await JsonReader.instance().readFromFile<ArkCmpCfg>(cfgfile);
86
+ if (cfg) {
87
+ this._analyzer.setConfig(cfg);
88
+ setResult = true;
89
+ }
90
+ }
91
+ if (!setResult) {
92
+ Log.warnX(this, "No configuration found, use default config.");
93
+ this._analyzer.setConfig(defaultArkCmpCfg());
94
+ }
95
+ console.log(this._analyzer.getConfig());
96
+ Log.infoX(this, "Set configuration successfully.");
97
+
98
+ let sort_type = args.get("sort_type") || 0;
99
+ let nodeName = args.get("node_name");
100
+ let outputDir: string = args.get("output") || './output';
101
+ let outputFileType: string = args.get("output_file") || 'console';
102
+ Log.infoX(this, `output:${outputDir}; type:${outputFileType}`);
103
+
104
+ this.takeAction(sort_type, outputDir, outputFileType, nodeName)
105
+ }
106
+
107
+ private async getOutputCfg(
108
+ output: IOutput,
109
+ outputDesc: any,
110
+ outputDir: string,
111
+ outputFile: string) : Promise<OutputCfg> {
112
+ const analyzerCfg = this._analyzer.getConfig() as ArkCmpCfg;
113
+ let cfg: OutputCfg = {
114
+ desc: outputDesc,
115
+ output: {
116
+ dir: outputDir,
117
+ filename: outputFile,
118
+ extension: output.type.toString(),
119
+ }
120
+ }
121
+ return cfg;
122
+ }
123
+
124
+ private async outputResults(
125
+ results: Array<any>,
126
+ outputEntity: IOutput,
127
+ outputCfg: OutputCfg): Promise<void> {
128
+ if (outputEntity.type === OutputType.CONSOLE) {
129
+ let data = new ConsoleData(false, results);
130
+ outputEntity.output(data, outputCfg);
131
+ } else if (outputEntity.type === OutputType.JSON) {
132
+ let data = new JsonData(outputCfg.desc, results);
133
+ outputEntity.output(data, outputCfg);
134
+ } else if (outputEntity.type === OutputType.TEXT) {
135
+ let data = new TextData(outputCfg.desc, JSON.stringify(results));
136
+ outputEntity.output(data, outputCfg);
137
+ } else if (outputEntity.type === OutputType.HTML) {
138
+ let data = new HtmlData(outputCfg.desc, JSON.stringify(results));
139
+ outputEntity.output(data, outputCfg);
140
+ } else {
141
+ Log.errorX(this, 'Invalid output file type.');
142
+ }
143
+ }
144
+
145
+ private async takeAction(sort_type: number, outputDir:string, output_type: string, node_name?: string): Promise<void> {
146
+ const analyzer = this._analyzer as ArkCompareAnalyzer;
147
+ const data_tmp = await analyzer.diffSnapshots(node_name);
148
+ const results = await analyzer.sortDiffs(sort_type, data_tmp);
149
+ let outputEntity: IOutput = OutputFactory.getOutput(output_type);
150
+ let outputCfg = await this.getOutputCfg(outputEntity, undefined, outputDir, '');
151
+ outputCfg.desc = {
152
+ "SourceSnapshot": analyzer.srcSnapshotFilePath,
153
+ "TargetSnapshot": analyzer.dstSnapshotFilePath,
154
+ "Action": "Compare Snapshots",
155
+ "NodeName": node_name || "None",
156
+ "Time": Date.now()
157
+ };
158
+ this.outputResults(results, outputEntity, outputCfg);
159
+ }
160
+ }