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,390 @@
1
+ import {
2
+ IHeapSnapshot,
3
+ IHeapNode,
4
+ IHeapEdge,
5
+ Nullable,
6
+ TraceFinder,
7
+ LeakTracePathItem
8
+ } from "@memlab/core";
9
+
10
+ /**
11
+ * 查找器
12
+ */
13
+ export class Finder {
14
+ private static traceFinder: TraceFinder = new TraceFinder();
15
+
16
+ /**
17
+ * 判断是否是指定名称属性的边
18
+ * @param edge 边
19
+ * @param propName 名称
20
+ * @returns true/false
21
+ */
22
+ public static isPropEdgeWithName(edge: IHeapEdge, propName: string) : boolean {
23
+ return edge.type === 'property' && edge.name_or_index === propName;
24
+ }
25
+
26
+ /**
27
+ * 判断是否是Proto属性的边
28
+ * @param edge 边
29
+ * @returns true/false
30
+ */
31
+ public static isProtoPropEdge(edge: IHeapEdge) {
32
+ return edge.type === 'property' && edge.name_or_index === 'Proto';
33
+ }
34
+
35
+ /**
36
+ * 判断是否是hclass属性的边
37
+ * @param edge 边
38
+ * @returns true/false
39
+ */
40
+ public static isHClassPropEdge(edge: IHeapEdge) {
41
+ return edge.type === 'property' && edge.name_or_index === 'hclass';
42
+ }
43
+
44
+ /**
45
+ * 共享内存类型
46
+ * 例举关键类型
47
+ */
48
+ public static OOM_SHARED_TYPES: string[] = [
49
+ 'js_shared_object',
50
+ 'js_shared_array',
51
+ 'js_shared_map',
52
+ 'js_shared_set'
53
+ ];
54
+
55
+ public static STRING_UNIQUE_ID = 'shared_heap_string_unique_id_0123456789';
56
+
57
+ public static isSharedHeapNode(node: IHeapNode) : boolean {
58
+ // String 类对象属于 shared heap
59
+ if (node.isString) {
60
+ return true
61
+ }
62
+ // 共享内存类型与节点名称匹配的
63
+ if (Finder.OOM_SHARED_TYPES.includes(node.name)) {
64
+ return true
65
+ }
66
+ // 先判断 Proto
67
+ let protoEdge = node.findAnyReference((edge: IHeapEdge) => { return Finder.isProtoPropEdge(edge) })
68
+ if (protoEdge) {
69
+ // 通过 proto 查找是否是 shared heap
70
+ if (this.OOM_SHARED_TYPES.includes(protoEdge.toNode.name)) {
71
+ return true
72
+ }
73
+ return this.isSharedHeapNode(protoEdge.toNode)
74
+ }
75
+ // 再判断 hclass
76
+ let hclassEdge = node.findAnyReference((edge: IHeapEdge) => { return this.isHClassPropEdge(edge) })
77
+ if (hclassEdge === null) {
78
+ return false
79
+ }
80
+ return this.isSharedHeapNode(hclassEdge.toNode)
81
+ }
82
+
83
+ public static getSharedHeapNodesMap(snapshot: IHeapSnapshot) : Map<string, Array<IHeapNode>> {
84
+ let nodesMap = new Map<string, Array<IHeapNode>>();
85
+ snapshot.nodes.forEach((node: IHeapNode, ) => {
86
+ if (Finder.isSharedHeapNode(node)) {
87
+ let tag = node.isString ? Finder.STRING_UNIQUE_ID : node.name;
88
+ let nodes = nodesMap.get(tag);
89
+ if (nodes === undefined) {
90
+ nodes = new Array<IHeapNode>();
91
+ }
92
+ nodes.push(node);
93
+ nodesMap.set(tag, nodes);
94
+ }
95
+ });
96
+ return nodesMap;
97
+ }
98
+
99
+ /**
100
+ * 获取所有shared heap节点的retained size大小总和
101
+ * @param snapshot heapsnapshot
102
+ */
103
+ public static getSharedHeapNodeRetainedSize(snapshot: IHeapSnapshot) : number {
104
+ let retained_size = 0;
105
+ snapshot.nodes.forEach((node: IHeapNode, ) => {
106
+ if (Finder.isSharedHeapNode(node)) {
107
+ retained_size += node.retainedSize;
108
+ }
109
+ });
110
+ return retained_size;
111
+ }
112
+
113
+ /**
114
+ * 获取所有string类型对象的retained size大小总和
115
+ * @param snapshot heapsnapshot
116
+ * @returns retained size of shared heap string
117
+ */
118
+ public static getStringRetainedSize(snapshot: IHeapSnapshot) : number {
119
+ let retained_size = 0;
120
+ snapshot.nodes.forEach((node: IHeapNode, ) => {
121
+ if (node.isString) {
122
+ retained_size += node.retainedSize;
123
+ }
124
+ });
125
+ return retained_size;
126
+ }
127
+
128
+ public static isSharedHeapNodeId(snapshot: IHeapSnapshot, nodeId: number) : boolean {
129
+ const node = snapshot.getNodeById(nodeId)
130
+ if (node === null) {
131
+ return false
132
+ }
133
+ return Finder.isSharedHeapNode(node)
134
+ }
135
+
136
+ /**
137
+ * 是否是GCRoot节点
138
+ * @param node 目标节点
139
+ * @returns true/false
140
+ */
141
+ public static isGCRoot(targetNode: IHeapNode): boolean {
142
+ return targetNode.numOfReferrers === 0;
143
+ }
144
+
145
+ /**
146
+ * 是否是Distance为1的节点
147
+ * @param targetNode 目标节点
148
+ * @returns true/false
149
+ */
150
+ public static isEqualDistanceOne(targetNode: IHeapNode): boolean {
151
+ let result = false;
152
+ targetNode.pathEdge
153
+ targetNode.referrers.forEach((referrer: IHeapEdge) => {
154
+ if (referrer.fromNode.numOfReferrers === 0) {
155
+ result = true;
156
+ }
157
+ });
158
+ return result;
159
+ }
160
+
161
+ /**
162
+ * 查找指定ID的节点
163
+ * @param snapshot 快照对象 IHeapSnapshot
164
+ * @param nodeId 节点ID
165
+ * @returns
166
+ */
167
+ public static findNodeById(snapshot: IHeapSnapshot, nodeId: number) : Nullable<IHeapNode> {
168
+ return snapshot.getNodeById(nodeId);
169
+ }
170
+
171
+ /**
172
+ * 查找满足过滤条件的节点
173
+ * @param snapshot 快照对象 IHeapSnapshot
174
+ * @param filter 过滤器
175
+ * @returns IHeapNode Array
176
+ */
177
+ public static findNodesByFilter(snapshot: IHeapSnapshot, filter: (node: IHeapNode) => boolean) : Array<IHeapNode> {
178
+ const result = new Array<IHeapNode>();
179
+ snapshot.nodes.forEach((node: IHeapNode, ) => {
180
+ if (filter(node)) {
181
+ result.push(node);
182
+ }
183
+ });
184
+ return result;
185
+ }
186
+
187
+ /**
188
+ * 按过滤器和过滤条件查找节点
189
+ * @param snapshot 快照对象 IHeapSnapshot
190
+ * @param filter 过滤器
191
+ * @param condition 过滤条件
192
+ * @returns IHeapNode Array
193
+ */
194
+ public static findNodesByFilterCondition(snapshot: IHeapSnapshot,
195
+ filter: (node: IHeapNode, condition: any) => boolean, condition: any) : Array<IHeapNode> {
196
+ const result = new Array<IHeapNode>();
197
+ snapshot.nodes.forEach((node: IHeapNode, ) => {
198
+ if (filter(node, condition)) {
199
+ result.push(node);
200
+ }
201
+ });
202
+ return result;
203
+ }
204
+
205
+ /**
206
+ * 查找所有GCRoot节点
207
+ * @param snapshot 快照对象 IHeapSnapshot
208
+ * @returns IHeapNode Array
209
+ */
210
+ public static findGCRoots(snapshot: IHeapSnapshot) : Array<IHeapNode> {
211
+ let filter = (node: IHeapNode) => Finder.isGCRoot(node);
212
+ return Finder.findNodesByFilter(snapshot, filter);
213
+ }
214
+
215
+ /**
216
+ * 查找Detached节点
217
+ * @param snapshot 快照对象 IHeapSnapshot
218
+ * @returns IHeapNode Array
219
+ */
220
+ public static findDetachedNodes(snapshot: IHeapSnapshot) : Array<IHeapNode> {
221
+ let filter = (node: IHeapNode) => node.is_detached;
222
+ return Finder.findNodesByFilter(snapshot, filter);
223
+ }
224
+
225
+ /**
226
+ * 查找指定个数的Detached节点
227
+ * @param snapshot 快照对象 IHeapSnapshot
228
+ * @param nodeName 节点名称
229
+ * @returns IHeapNode Array
230
+ */
231
+ public static findDetachedNodesByName(snapshot: IHeapSnapshot, nodeName: string) : Array<IHeapNode> {
232
+ const result = new Array<IHeapNode>();
233
+ snapshot.nodes.forEach((node: IHeapNode, ) => {
234
+ if (node.is_detached && node.name === nodeName) {
235
+ result.push(node);
236
+ }
237
+ });
238
+ return result;
239
+ }
240
+
241
+ /**
242
+ * find nodes by distance from gc root
243
+ * @param snapshot snapshot
244
+ * @param distance distance <= 1
245
+ * @returns Array<IHeapNode>
246
+ */
247
+ public static findNodesByDistanceOne(snapshot: IHeapSnapshot, includeGCRoot: boolean = false) : Array<IHeapNode> {
248
+ let filter = (node: IHeapNode) => {
249
+ return (includeGCRoot && Finder.isGCRoot(node)) || Finder.isEqualDistanceOne(node);
250
+ };
251
+ return Finder.findNodesByFilter(snapshot, filter);
252
+ }
253
+
254
+ /**
255
+ * 查找指定节点名称的节点
256
+ * @param snapshot 快照对象 IHeapSnapshot
257
+ * @param nodeName 节点名称
258
+ * @returns IHeapNode Array
259
+ */
260
+ public static findNodesByName(snapshot: IHeapSnapshot, nodeName: string) : Array<IHeapNode> {
261
+ let filter = (node: IHeapNode) => {
262
+ return node.name == nodeName;
263
+ };
264
+ return Finder.findNodesByFilter(snapshot, filter);
265
+ }
266
+
267
+ /**
268
+ * 查找指定节点名称的节点,最大个数为
269
+ * @param snapshot 快照对象 IHeapSnapshot
270
+ * @param nodeName 节点名称
271
+ * @param count 查找对象个数(按节点id号排序)
272
+ * @param reverse 是否倒序查找
273
+ * @returns IHeapNode Array
274
+ */
275
+ public static findNodesByNameCount(
276
+ snapshot: IHeapSnapshot,
277
+ nodeName: string,
278
+ count: number) : Array<IHeapNode> {
279
+ const result = new Array<IHeapNode>();
280
+ let nodeCount = 0;
281
+ snapshot.nodes.forEach((node, )=> {
282
+ if((node.name == nodeName) && (nodeCount < count)) {
283
+ result.push(node);
284
+ nodeCount += 1;
285
+ }
286
+ });
287
+ return result;
288
+ }
289
+
290
+ /**
291
+ *
292
+ * @param snapshot 快照对象 IHeapSnapshot
293
+ * @param nodeName 节点名称
294
+ * @returns
295
+ */
296
+ public static findNodesByNameDistanceOne(snapshot: IHeapSnapshot, nodeName: string, includeGCRoot: boolean = false) : Array<IHeapNode> {
297
+ let filter = (node: IHeapNode) => {
298
+ return (node.name === nodeName)
299
+ && ((includeGCRoot && Finder.isGCRoot(node)) || Finder.isEqualDistanceOne(node));
300
+ };
301
+ return Finder.findNodesByFilter(snapshot, filter);
302
+ }
303
+
304
+ /**
305
+ * 查找指定节点的最短引用路径
306
+ * @param snapshot 快照对象 IHeapSnapshot
307
+ * @param targetNode 节点对象
308
+ * @returns 引用链路径
309
+ */
310
+ public static findShortestPathToGCRoot(snapshot: IHeapSnapshot, targetNode: IHeapNode): LeakTracePathItem | undefined {
311
+ Finder.traceFinder.annotateShortestPaths(snapshot); // 标记最短路径
312
+ const optPath = Finder.traceFinder.getPathToGCRoots(snapshot, targetNode);
313
+ return optPath ? optPath : undefined;
314
+ }
315
+
316
+ /**
317
+ * 查找指定节点数组的所有最短引用路径
318
+ * @param snapshot 快照对象 IHeapSnapshot
319
+ * @param targetNodes 节点对象数组
320
+ * @returns 引用链路径数组
321
+ */
322
+ public static findShortestPaths(snapshot: IHeapSnapshot, targetNodes: IHeapNode[]): Array<LeakTracePathItem> {
323
+ const result: Array<LeakTracePathItem> = new Array<LeakTracePathItem>();
324
+ Finder.traceFinder.annotateShortestPaths(snapshot);
325
+ targetNodes.forEach(node => {
326
+ const optPath = Finder.traceFinder.getPathToGCRoots(snapshot, node);
327
+ if (optPath) {
328
+ result.push(optPath);
329
+ }
330
+ });
331
+ return result;
332
+ }
333
+
334
+ /**
335
+ * 获取堆节点的最短路径
336
+ * @param node 堆节点
337
+ * @returns 最短路径的节点名称数组
338
+ * @example
339
+ */
340
+ public static getShortestPath(node: IHeapNode): [number[], string[], number] {
341
+ const shortestPathNodeIds: number[] = []
342
+ const shortestPathStrings: string[] = []
343
+ let distance = 0;
344
+ let shortestPathNode = node
345
+ while (shortestPathNode && shortestPathNode.hasPathEdge) {
346
+ let edge = shortestPathNode.pathEdge
347
+ if (edge) {
348
+ distance++;
349
+ shortestPathNodeIds.push(edge.fromNode.id);
350
+ shortestPathStrings.push(edge.fromNode.name);
351
+ shortestPathNode = edge.fromNode
352
+ }
353
+ }
354
+ return [shortestPathNodeIds, shortestPathStrings, distance];
355
+ }
356
+
357
+ /**
358
+ * 获取节点模块名(兼容5.x & 6.0)
359
+ * @param name 节点名称
360
+ * @returns module name
361
+ */
362
+ public static getModuleName(name: string): string {
363
+ let nameSplit = name.split('#');
364
+ if (nameSplit.length > 1) {
365
+ // 6.0
366
+ return nameSplit[0];
367
+ }
368
+ // 5.x
369
+ return name.split(' ')[0];
370
+ }
371
+
372
+ /**
373
+ * 获取节点Class名(兼容5.x & 6.0)
374
+ * @param name 节点名称
375
+ * @returns class name
376
+ */
377
+ public static getClassName(name: string): string {
378
+ let regex = /^(.*?)\(line:\d+\).*?$/;
379
+ const match = regex.exec(name);
380
+ if (match) {
381
+ return match[1];
382
+ }
383
+ let regex5 = /^(.*?)\(.*?\)$/;
384
+ const match5 = regex5.exec(name);
385
+ if (match5) {
386
+ return match5[1]
387
+ }
388
+ return name;
389
+ }
390
+ }
@@ -0,0 +1,53 @@
1
+ import { IHeapSnapshot, utils, AnyOptions } from "@memlab/core";
2
+ import { getFullHeapFromFile } from "@memlab/heap-analysis";
3
+ import { Log } from "../utils/Log";
4
+
5
+ /**
6
+ * Loader
7
+ */
8
+ export class Loader {
9
+ public static readonly DOMAIN = 'HeapSnapshot';
10
+ public static readonly TAG = 'Loader';
11
+
12
+ /**
13
+ * 加载HeapSnapshot文件
14
+ * @param file 文件路径
15
+ * @param log 是否打印日志
16
+ * @returns IHeapSnapshot 对象
17
+ */
18
+ public static async loadFromFile(file: string, log: boolean = false) : Promise<IHeapSnapshot> {
19
+ if (log) Log.info(Loader.DOMAIN, Loader.TAG, `Loading heapsnapshot from file: ${file}`);
20
+ const snapshot = await getFullHeapFromFile(file);
21
+ if (log) Log.info(Loader.DOMAIN, Loader.TAG, `Loaded heapsnapshot from file: ${file}`);
22
+ return snapshot;
23
+ }
24
+
25
+ /**
26
+ * 加载HeapSnapshot文件
27
+ * @param file 文件路径
28
+ * @param options 可选参数选项
29
+ * @param log 是否打印日志
30
+ * @returns IHeapSnapshot 对象
31
+ */
32
+ public static async loadFromFileOption(file: string,
33
+ options: AnyOptions, log: boolean = false) : Promise<IHeapSnapshot> {
34
+ if (log) Log.info(Loader.DOMAIN, Loader.TAG, `Loading heapsnapshot from file: ${file}`);
35
+ const snapshot = await utils.getSnapshotFromFile(file, options);
36
+ if (log) Log.info(Loader.DOMAIN, Loader.TAG, `Loaded heapsnapshot from file: ${file}`);
37
+ return snapshot
38
+ }
39
+
40
+ /**
41
+ * Heapsnapshot 多文件加载
42
+ * @param files 多文件路径集合
43
+ * @returns IHeapSnapshot 对象集合
44
+ */
45
+ public static async loadFromFiles(files: Array<string>) : Promise<Array<IHeapSnapshot>> {
46
+ const result = new Array<IHeapSnapshot>();
47
+ files.forEach(async (file) => {
48
+ const heap = await getFullHeapFromFile(file);
49
+ result.push(heap);
50
+ });
51
+ return result;
52
+ }
53
+ }
@@ -0,0 +1,252 @@
1
+ /**
2
+ * Logger interface
3
+ */
4
+ export interface ILogger {
5
+ /**
6
+ * print debug message
7
+ * @param domain log domain
8
+ * @param tag log tag
9
+ * @param message log message
10
+ */
11
+ debug(domain: string, tag: string, message: string) : void;
12
+
13
+ /**
14
+ * print info message
15
+ * @param domain log domain
16
+ * @param tag log tag
17
+ * @param message log message
18
+ */
19
+ info(domain: string, tag: string, message: string) : void;
20
+
21
+ /**
22
+ * print warn message
23
+ * @param domain log domain
24
+ * @param tag log tag
25
+ * @param message log message
26
+ */
27
+ warn(domain: string, tag: string, message: string) : void;
28
+
29
+ /**
30
+ * print error message
31
+ * @param domain log domain
32
+ * @param tag log tag
33
+ * @param message log message
34
+ */
35
+ error(domain: string, tag: string, message: string) : void;
36
+
37
+ /**
38
+ * print fatal message
39
+ * @param domain log domain
40
+ * @param tag log tag
41
+ * @param message log message
42
+ */
43
+ fatal(domain: string, tag: string, message: string) : void;
44
+ }
45
+
46
+ /**
47
+ * Log Type
48
+ */
49
+ export enum LogType {
50
+ DEBUG = 'DEBUG',
51
+ INFO = 'INFO',
52
+ WARN = 'WARN',
53
+ ERROR = 'ERROR',
54
+ FATAL = 'FATAL'
55
+ }
56
+
57
+ /**
58
+ * Loggable interface
59
+ */
60
+ export interface ILoggable {
61
+ /**
62
+ * Domain
63
+ */
64
+ DOMAIN: string;
65
+ /**
66
+ * Tag
67
+ */
68
+ TAG: string;
69
+ }
70
+
71
+ /**
72
+ * Logger class
73
+ */
74
+ class Logger implements ILogger {
75
+ private _enableTime: boolean;
76
+
77
+ constructor(enableTime: boolean = true) {
78
+ this._enableTime = enableTime;
79
+ }
80
+
81
+ /**
82
+ * print log
83
+ * @param logType log type
84
+ * @param domain domain
85
+ * @param tag tag
86
+ * @param message message
87
+ */
88
+ private print(logType: LogType, domain: string, tag: string, message: string) {
89
+ const curTime = this._enableTime ? `${new Date().toISOString().replace('Z', '')}` : '*';
90
+ console.log(`${curTime} | [${logType}] | ${domain}-${tag}: ${message}`);
91
+ }
92
+
93
+ /**
94
+ * print debug message
95
+ * @param domain log domain
96
+ * @param tag log tag
97
+ * @param message log message
98
+ */
99
+ public debug(domain: string, tag: string, message: string) {
100
+ this.print(LogType.DEBUG, domain, tag, message)
101
+ }
102
+
103
+ /**
104
+ * print info message
105
+ * @param domain log domain
106
+ * @param tag log tag
107
+ * @param message log message
108
+ */
109
+ public info(domain: string, tag: string, message: string) {
110
+ this.print(LogType.INFO, domain, tag, message)
111
+ }
112
+
113
+ /**
114
+ * print warn message
115
+ * @param domain log domain
116
+ * @param tag log tag
117
+ * @param message log message
118
+ */
119
+ public warn(domain: string, tag: string, message: string) {
120
+ this.print(LogType.WARN, domain, tag, message)
121
+ }
122
+
123
+ /**
124
+ * print error message
125
+ * @param domain log domain
126
+ * @param tag log tag
127
+ * @param message log message
128
+ */
129
+ public error(domain: string, tag: string, message: string) {
130
+ this.print(LogType.ERROR, domain, tag, message)
131
+ }
132
+
133
+ /**
134
+ * print fatal message
135
+ * @param domain log domain
136
+ * @param tag log tag
137
+ * @param message log message
138
+ */
139
+ public fatal(domain: string, tag: string, message: string) {
140
+ this.print(LogType.FATAL, domain, tag, message)
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Log class
146
+ */
147
+ export class Log {
148
+ private static _logger: ILogger = new Logger(true);
149
+
150
+ /**
151
+ * set logger instance
152
+ * @param logger logger instance
153
+ */
154
+ public static setLogger(logger: ILogger) {
155
+ this._logger = logger;
156
+ }
157
+
158
+ /**
159
+ * print debug message
160
+ * @param domain log domain
161
+ * @param tag log tag
162
+ * @param message log message
163
+ */
164
+ public static debug(domain: string, tag: string, message: string) {
165
+ this._logger.debug(domain, tag, message);
166
+ }
167
+
168
+ /**
169
+ * print info message
170
+ * @param domain log domain
171
+ * @param tag log tag
172
+ * @param message log message
173
+ */
174
+ public static info(domain: string, tag: string, message: string) {
175
+ this._logger.info(domain, tag, message);
176
+ }
177
+
178
+ /**
179
+ * print warn message
180
+ * @param domain log domain
181
+ * @param tag log tag
182
+ * @param message log message
183
+ */
184
+ public static warn(domain: string, tag: string, message: string) {
185
+ this._logger.warn(domain, tag, message);
186
+ }
187
+
188
+ /**
189
+ * print error message
190
+ * @param domain log domain
191
+ * @param tag log tag
192
+ * @param message log message
193
+ */
194
+ public static error(domain: string, tag: string, message: string) {
195
+ this._logger.error(domain, tag, message);
196
+ }
197
+
198
+ /**
199
+ * print fatal message
200
+ * @param domain log domain
201
+ * @param tag log tag
202
+ * @param message log message
203
+ */
204
+ public static fatal(domain: string, tag: string, message: string) {
205
+ this._logger.fatal(domain, tag, message);
206
+ }
207
+
208
+ /**
209
+ * print debug message
210
+ * @param instance loggable instance
211
+ * @param message log message
212
+ */
213
+ public static debugX(instance: ILoggable, message: string) {
214
+ this._logger.debug(instance.DOMAIN, instance.TAG, message);
215
+ }
216
+
217
+ /**
218
+ * print info message
219
+ * @param instance loggable instance
220
+ * @param message log message
221
+ */
222
+ public static infoX(instance: ILoggable, message: string) {
223
+ this._logger.info(instance.DOMAIN, instance.TAG, message);
224
+ }
225
+
226
+ /**
227
+ * print warn message
228
+ * @param instance loggable instance
229
+ * @param message log message
230
+ */
231
+ public static warnX(instance: ILoggable, message: string) {
232
+ this._logger.warn(instance.DOMAIN, instance.TAG, message);
233
+ }
234
+
235
+ /**
236
+ * print error message
237
+ * @param instance loggable instance
238
+ * @param message log message
239
+ */
240
+ public static errorX(instance: ILoggable, message: string) {
241
+ this._logger.error(instance.DOMAIN, instance.TAG, message);
242
+ }
243
+
244
+ /**
245
+ * print fatal message
246
+ * @param instance loggable instance
247
+ * @param message log message
248
+ */
249
+ public static fatalX(instance: ILoggable, message: string) {
250
+ this._logger.fatal(instance.DOMAIN, instance.TAG, message);
251
+ }
252
+ }