@ananotherdeveloper/drain3js 0.9.11-rev1
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/LICENSE +25 -0
- package/README.md +237 -0
- package/dist/drain.d.ts +67 -0
- package/dist/drain.d.ts.map +1 -0
- package/dist/drain.js +442 -0
- package/dist/drain.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/jaccard-drain.d.ts +9 -0
- package/dist/jaccard-drain.d.ts.map +1 -0
- package/dist/jaccard-drain.js +214 -0
- package/dist/jaccard-drain.js.map +1 -0
- package/dist/masking.d.ts +23 -0
- package/dist/masking.d.ts.map +1 -0
- package/dist/masking.js +59 -0
- package/dist/masking.js.map +1 -0
- package/dist/persistence/file-persistence.d.ts +8 -0
- package/dist/persistence/file-persistence.d.ts.map +1 -0
- package/dist/persistence/file-persistence.js +18 -0
- package/dist/persistence/file-persistence.js.map +1 -0
- package/dist/persistence/index.d.ts +4 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/index.js +4 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/memory-buffer-persistence.d.ts +7 -0
- package/dist/persistence/memory-buffer-persistence.d.ts.map +1 -0
- package/dist/persistence/memory-buffer-persistence.js +11 -0
- package/dist/persistence/memory-buffer-persistence.js.map +1 -0
- package/dist/persistence/persistence-handler.d.ts +5 -0
- package/dist/persistence/persistence-handler.d.ts.map +1 -0
- package/dist/persistence/persistence-handler.js +3 -0
- package/dist/persistence/persistence-handler.js.map +1 -0
- package/dist/simple-profiler.d.ts +34 -0
- package/dist/simple-profiler.d.ts.map +1 -0
- package/dist/simple-profiler.js +135 -0
- package/dist/simple-profiler.js.map +1 -0
- package/dist/template-miner-config.d.ts +48 -0
- package/dist/template-miner-config.d.ts.map +1 -0
- package/dist/template-miner-config.js +73 -0
- package/dist/template-miner-config.js.map +1 -0
- package/dist/template-miner.d.ts +35 -0
- package/dist/template-miner.d.ts.map +1 -0
- package/dist/template-miner.js +258 -0
- package/dist/template-miner.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// This file implements the Drain algorithm for log parsing using Jaccard similarity.
|
|
3
|
+
import { DrainBase, Node } from './drain.js';
|
|
4
|
+
export class JaccardDrain extends DrainBase {
|
|
5
|
+
treeSearch(rootNode, tokens, simTh, includeParams) {
|
|
6
|
+
const tokenCount = tokens.length;
|
|
7
|
+
let tokenFirst;
|
|
8
|
+
if (tokens.length === 0) {
|
|
9
|
+
tokenFirst = '';
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
tokenFirst = tokens[0];
|
|
13
|
+
}
|
|
14
|
+
const firstNode = rootNode.keyToChildNode.get(tokenFirst);
|
|
15
|
+
if (firstNode === undefined) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
// handle case of empty log string
|
|
19
|
+
if (tokenCount === 0) {
|
|
20
|
+
return this.idToCluster.peek(firstNode.clusterIds[0]) ?? null;
|
|
21
|
+
}
|
|
22
|
+
let curNode = firstNode;
|
|
23
|
+
let curNodeDepth = 1;
|
|
24
|
+
for (const token of tokens.slice(1)) {
|
|
25
|
+
if (curNodeDepth >= this.maxNodeDepth) {
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
if (curNodeDepth === tokenCount - 1) {
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
const keyToChildNode = curNode.keyToChildNode;
|
|
32
|
+
let nextNode = keyToChildNode.get(token);
|
|
33
|
+
if (nextNode === undefined) {
|
|
34
|
+
nextNode = keyToChildNode.get(this.paramStr);
|
|
35
|
+
}
|
|
36
|
+
if (nextNode === undefined) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
curNode = nextNode;
|
|
40
|
+
curNodeDepth += 1;
|
|
41
|
+
}
|
|
42
|
+
return this.fastMatch(curNode.clusterIds, tokens, simTh, includeParams);
|
|
43
|
+
}
|
|
44
|
+
addSeqToPrefixTree(rootNode, cluster) {
|
|
45
|
+
const tokenCount = cluster.logTemplateTokens.length;
|
|
46
|
+
let tokenFirst;
|
|
47
|
+
if (cluster.logTemplateTokens.length === 0) {
|
|
48
|
+
tokenFirst = '';
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
tokenFirst = cluster.logTemplateTokens[0];
|
|
52
|
+
}
|
|
53
|
+
let firstLayerNode = rootNode.keyToChildNode.get(tokenFirst);
|
|
54
|
+
if (firstLayerNode === undefined) {
|
|
55
|
+
firstLayerNode = new Node();
|
|
56
|
+
rootNode.keyToChildNode.set(tokenFirst, firstLayerNode);
|
|
57
|
+
}
|
|
58
|
+
let curNode = firstLayerNode;
|
|
59
|
+
// handle case of empty log string
|
|
60
|
+
if (tokenCount === 0) {
|
|
61
|
+
curNode.clusterIds = [cluster.clusterId];
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// only one word: add into current node
|
|
65
|
+
if (tokenCount === 1) {
|
|
66
|
+
const newClusterIds = [];
|
|
67
|
+
for (const clusterId of curNode.clusterIds) {
|
|
68
|
+
if (this.idToCluster.has(clusterId)) {
|
|
69
|
+
newClusterIds.push(clusterId);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
newClusterIds.push(cluster.clusterId);
|
|
73
|
+
curNode.clusterIds = newClusterIds;
|
|
74
|
+
}
|
|
75
|
+
let currentDepth = 1;
|
|
76
|
+
for (const token of cluster.logTemplateTokens.slice(1)) {
|
|
77
|
+
if (currentDepth >= this.maxNodeDepth || currentDepth >= tokenCount - 1) {
|
|
78
|
+
const newClusterIds = [];
|
|
79
|
+
for (const clusterId of curNode.clusterIds) {
|
|
80
|
+
if (this.idToCluster.has(clusterId)) {
|
|
81
|
+
newClusterIds.push(clusterId);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
newClusterIds.push(cluster.clusterId);
|
|
85
|
+
curNode.clusterIds = newClusterIds;
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
if (!curNode.keyToChildNode.has(token)) {
|
|
89
|
+
if (this.parametrizeNumericTokens && DrainBase.hasNumbers(token)) {
|
|
90
|
+
if (!curNode.keyToChildNode.has(this.paramStr)) {
|
|
91
|
+
const newNode = new Node();
|
|
92
|
+
curNode.keyToChildNode.set(this.paramStr, newNode);
|
|
93
|
+
curNode = newNode;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
curNode = curNode.keyToChildNode.get(this.paramStr);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
if (curNode.keyToChildNode.has(this.paramStr)) {
|
|
101
|
+
if (curNode.keyToChildNode.size < this.maxChildren) {
|
|
102
|
+
const newNode = new Node();
|
|
103
|
+
curNode.keyToChildNode.set(token, newNode);
|
|
104
|
+
curNode = newNode;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
curNode = curNode.keyToChildNode.get(this.paramStr);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
if (curNode.keyToChildNode.size + 1 < this.maxChildren) {
|
|
112
|
+
const newNode = new Node();
|
|
113
|
+
curNode.keyToChildNode.set(token, newNode);
|
|
114
|
+
curNode = newNode;
|
|
115
|
+
}
|
|
116
|
+
else if (curNode.keyToChildNode.size + 1 === this.maxChildren) {
|
|
117
|
+
const newNode = new Node();
|
|
118
|
+
curNode.keyToChildNode.set(this.paramStr, newNode);
|
|
119
|
+
curNode = newNode;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
curNode = curNode.keyToChildNode.get(this.paramStr);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
curNode = curNode.keyToChildNode.get(token);
|
|
129
|
+
}
|
|
130
|
+
currentDepth += 1;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
getSeqDistance(seq1, seq2, includeParams) {
|
|
134
|
+
if (seq1.length === 0) {
|
|
135
|
+
return [1.0, 0];
|
|
136
|
+
}
|
|
137
|
+
let paramCount = 0;
|
|
138
|
+
for (const token1 of seq1) {
|
|
139
|
+
if (token1 === this.paramStr) {
|
|
140
|
+
paramCount += 1;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
let filteredSeq2 = seq2;
|
|
144
|
+
// If the token and the data have the same length, and there are param_str in the token
|
|
145
|
+
if (seq1.length === seq2.length && paramCount > 0) {
|
|
146
|
+
filteredSeq2 = seq2.filter((_, i) => seq1[i] !== this.paramStr);
|
|
147
|
+
}
|
|
148
|
+
let filteredSeq1;
|
|
149
|
+
if (includeParams) {
|
|
150
|
+
filteredSeq1 = seq1.filter((x) => x !== this.paramStr);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
filteredSeq1 = seq1;
|
|
154
|
+
}
|
|
155
|
+
const set1 = new Set(filteredSeq1);
|
|
156
|
+
const set2 = new Set(filteredSeq2);
|
|
157
|
+
let intersectionSize = 0;
|
|
158
|
+
for (const item of set1) {
|
|
159
|
+
if (set2.has(item)) {
|
|
160
|
+
intersectionSize++;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const unionSet = new Set([...set1, ...set2]);
|
|
164
|
+
let retVal = intersectionSize / unionSet.size;
|
|
165
|
+
// Apply gain
|
|
166
|
+
retVal = retVal * 1.3 < 1 ? retVal * 1.3 : 1;
|
|
167
|
+
return [retVal, paramCount];
|
|
168
|
+
}
|
|
169
|
+
createTemplate(seq1, seq2) {
|
|
170
|
+
const interSet = new Set([...seq1].filter((x) => seq2.includes(x)));
|
|
171
|
+
if (seq1.length === seq2.length) {
|
|
172
|
+
const retVal = [...seq2];
|
|
173
|
+
for (let i = 0; i < seq1.length; i++) {
|
|
174
|
+
if (seq1[i] !== seq2[i]) {
|
|
175
|
+
retVal[i] = this.paramStr;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return retVal;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
const retVal = seq1.length > seq2.length ? [...seq1] : [...seq2];
|
|
182
|
+
for (let i = 0; i < retVal.length; i++) {
|
|
183
|
+
if (!interSet.has(retVal[i])) {
|
|
184
|
+
retVal[i] = this.paramStr;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return retVal;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
match(content, fullSearchStrategy = 'never') {
|
|
191
|
+
if (!['always', 'never', 'fallback'].includes(fullSearchStrategy)) {
|
|
192
|
+
throw new Error(`Invalid full_search_strategy: ${fullSearchStrategy}`);
|
|
193
|
+
}
|
|
194
|
+
const requiredSimTh = 0.8;
|
|
195
|
+
const contentTokens = this.getContentAsTokens(content);
|
|
196
|
+
const fullSearch = () => {
|
|
197
|
+
const firstToken = contentTokens.length > 0 ? contentTokens[0] : '';
|
|
198
|
+
const allIds = this.getClustersIdsForSeqLen(firstToken);
|
|
199
|
+
return this.fastMatch(allIds, contentTokens, requiredSimTh, true);
|
|
200
|
+
};
|
|
201
|
+
if (fullSearchStrategy === 'always') {
|
|
202
|
+
return fullSearch();
|
|
203
|
+
}
|
|
204
|
+
const matchCluster = this.treeSearch(this.rootNode, contentTokens, requiredSimTh, true);
|
|
205
|
+
if (matchCluster !== null) {
|
|
206
|
+
return matchCluster;
|
|
207
|
+
}
|
|
208
|
+
if (fullSearchStrategy === 'never') {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
return fullSearch();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=jaccard-drain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jaccard-drain.js","sourceRoot":"","sources":["../src/jaccard-drain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare abstract class AbstractMaskingInstruction {
|
|
2
|
+
maskWith: string;
|
|
3
|
+
constructor(maskWith: string);
|
|
4
|
+
abstract mask(content: string, maskPrefix: string, maskSuffix: string): string;
|
|
5
|
+
}
|
|
6
|
+
export declare class MaskingInstruction extends AbstractMaskingInstruction {
|
|
7
|
+
regex: RegExp;
|
|
8
|
+
constructor(pattern: string, maskWith: string);
|
|
9
|
+
get pattern(): string;
|
|
10
|
+
mask(content: string, maskPrefix: string, maskSuffix: string): string;
|
|
11
|
+
}
|
|
12
|
+
export declare const RegexMaskingInstruction: typeof MaskingInstruction;
|
|
13
|
+
export declare class LogMasker {
|
|
14
|
+
maskPrefix: string;
|
|
15
|
+
maskSuffix: string;
|
|
16
|
+
maskingInstructions: AbstractMaskingInstruction[];
|
|
17
|
+
private maskNameToInstructions;
|
|
18
|
+
constructor(maskingInstructions: AbstractMaskingInstruction[], maskPrefix: string, maskSuffix: string);
|
|
19
|
+
mask(content: string): string;
|
|
20
|
+
get maskNames(): Iterable<string>;
|
|
21
|
+
instructionsByMaskName(maskName: string): AbstractMaskingInstruction[];
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=masking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"masking.d.ts","sourceRoot":"","sources":["../src/masking.ts"],"names":[],"mappings":"AAEA,8BAAsB,0BAA0B;IAC9C,QAAQ,EAAE,MAAM,CAAC;gBAEL,QAAQ,EAAE,MAAM;IAI5B,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;CAC/E;AAED,qBAAa,kBAAmB,SAAQ,0BAA0B;IAChE,KAAK,EAAE,MAAM,CAAC;gBAEF,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAK7C,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;CAMtE;AAGD,eAAO,MAAM,uBAAuB,2BAAqB,CAAC;AAE1D,qBAAa,SAAS;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,0BAA0B,EAAE,CAAC;IAClD,OAAO,CAAC,sBAAsB,CAA4C;gBAE9D,mBAAmB,EAAE,0BAA0B,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;IAerG,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAO7B,IAAI,SAAS,IAAI,QAAQ,CAAC,MAAM,CAAC,CAEhC;IAED,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,0BAA0B,EAAE;CAGvE"}
|
package/dist/masking.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
export class AbstractMaskingInstruction {
|
|
3
|
+
maskWith;
|
|
4
|
+
constructor(maskWith) {
|
|
5
|
+
this.maskWith = maskWith;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export class MaskingInstruction extends AbstractMaskingInstruction {
|
|
9
|
+
regex;
|
|
10
|
+
constructor(pattern, maskWith) {
|
|
11
|
+
super(maskWith);
|
|
12
|
+
this.regex = new RegExp(pattern, 'g');
|
|
13
|
+
}
|
|
14
|
+
get pattern() {
|
|
15
|
+
return this.regex.source;
|
|
16
|
+
}
|
|
17
|
+
mask(content, maskPrefix, maskSuffix) {
|
|
18
|
+
const maskStr = maskPrefix + this.maskWith + maskSuffix;
|
|
19
|
+
// Reset lastIndex for global regex
|
|
20
|
+
this.regex.lastIndex = 0;
|
|
21
|
+
return content.replace(this.regex, maskStr);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// Alias for MaskingInstruction
|
|
25
|
+
export const RegexMaskingInstruction = MaskingInstruction;
|
|
26
|
+
export class LogMasker {
|
|
27
|
+
maskPrefix;
|
|
28
|
+
maskSuffix;
|
|
29
|
+
maskingInstructions;
|
|
30
|
+
maskNameToInstructions;
|
|
31
|
+
constructor(maskingInstructions, maskPrefix, maskSuffix) {
|
|
32
|
+
this.maskPrefix = maskPrefix;
|
|
33
|
+
this.maskSuffix = maskSuffix;
|
|
34
|
+
this.maskingInstructions = maskingInstructions;
|
|
35
|
+
this.maskNameToInstructions = new Map();
|
|
36
|
+
for (const mi of this.maskingInstructions) {
|
|
37
|
+
const existing = this.maskNameToInstructions.get(mi.maskWith);
|
|
38
|
+
if (existing) {
|
|
39
|
+
existing.push(mi);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
this.maskNameToInstructions.set(mi.maskWith, [mi]);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
mask(content) {
|
|
47
|
+
for (const mi of this.maskingInstructions) {
|
|
48
|
+
content = mi.mask(content, this.maskPrefix, this.maskSuffix);
|
|
49
|
+
}
|
|
50
|
+
return content;
|
|
51
|
+
}
|
|
52
|
+
get maskNames() {
|
|
53
|
+
return this.maskNameToInstructions.keys();
|
|
54
|
+
}
|
|
55
|
+
instructionsByMaskName(maskName) {
|
|
56
|
+
return this.maskNameToInstructions.get(maskName) ?? [];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=masking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"masking.js","sourceRoot":"","sources":["../src/masking.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAE/B,MAAM,OAAgB,0BAA0B;IAC9C,QAAQ,CAAS;IAEjB,YAAY,QAAgB;QAC1B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CAGF;AAED,MAAM,OAAO,kBAAmB,SAAQ,0BAA0B;IAChE,KAAK,CAAS;IAEd,YAAY,OAAe,EAAE,QAAgB;QAC3C,KAAK,CAAC,QAAQ,CAAC,CAAC;QAChB,IAAI,CAAC,KAAK,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,UAAkB,EAAE,UAAkB;QAC1D,MAAM,OAAO,GAAG,UAAU,GAAG,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC;QACxD,mCAAmC;QACnC,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;QACzB,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;CACF;AAED,+BAA+B;AAC/B,MAAM,CAAC,MAAM,uBAAuB,GAAG,kBAAkB,CAAC;AAE1D,MAAM,OAAO,SAAS;IACpB,UAAU,CAAS;IACnB,UAAU,CAAS;IACnB,mBAAmB,CAA+B;IAC1C,sBAAsB,CAA4C;IAE1E,YAAY,mBAAiD,EAAE,UAAkB,EAAE,UAAkB;QACnG,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,mBAAmB,GAAG,mBAAmB,CAAC;QAC/C,IAAI,CAAC,sBAAsB,GAAG,IAAI,GAAG,EAAE,CAAC;QACxC,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;YAC9D,IAAI,QAAQ,EAAE,CAAC;gBACb,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpB,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACrD,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAe;QAClB,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC1C,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,sBAAsB,CAAC,IAAI,EAAE,CAAC;IAC5C,CAAC;IAED,sBAAsB,CAAC,QAAgB;QACrC,OAAO,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IACzD,CAAC;CACF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PersistenceHandler } from './persistence-handler.js';
|
|
2
|
+
export declare class FilePersistence implements PersistenceHandler {
|
|
3
|
+
private filePath;
|
|
4
|
+
constructor(filePath: string);
|
|
5
|
+
saveState(state: Buffer): void;
|
|
6
|
+
loadState(): Buffer | null;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=file-persistence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-persistence.d.ts","sourceRoot":"","sources":["../../src/persistence/file-persistence.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,qBAAa,eAAgB,YAAW,kBAAkB;IACxD,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,EAAE,MAAM;IAI5B,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI9B,SAAS,IAAI,MAAM,GAAG,IAAI;CAM3B"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
export class FilePersistence {
|
|
4
|
+
filePath;
|
|
5
|
+
constructor(filePath) {
|
|
6
|
+
this.filePath = filePath;
|
|
7
|
+
}
|
|
8
|
+
saveState(state) {
|
|
9
|
+
fs.writeFileSync(this.filePath, state);
|
|
10
|
+
}
|
|
11
|
+
loadState() {
|
|
12
|
+
if (!fs.existsSync(this.filePath)) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
return fs.readFileSync(this.filePath);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=file-persistence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-persistence.js","sourceRoot":"","sources":["../../src/persistence/file-persistence.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAE/B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAG9B,MAAM,OAAO,eAAe;IAClB,QAAQ,CAAS;IAEzB,YAAY,QAAgB;QAC1B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,SAAS,CAAC,KAAa;QACrB,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACzC,CAAC;IAED,SAAS;QACP,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/persistence/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/persistence/index.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAE/B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PersistenceHandler } from './persistence-handler.js';
|
|
2
|
+
export declare class MemoryBufferPersistence implements PersistenceHandler {
|
|
3
|
+
private state;
|
|
4
|
+
saveState(state: Buffer): void;
|
|
5
|
+
loadState(): Buffer | null;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=memory-buffer-persistence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-buffer-persistence.d.ts","sourceRoot":"","sources":["../../src/persistence/memory-buffer-persistence.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,qBAAa,uBAAwB,YAAW,kBAAkB;IAChE,OAAO,CAAC,KAAK,CAAuB;IAEpC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI9B,SAAS,IAAI,MAAM,GAAG,IAAI;CAG3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-buffer-persistence.js","sourceRoot":"","sources":["../../src/persistence/memory-buffer-persistence.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAI/B,MAAM,OAAO,uBAAuB;IAC1B,KAAK,GAAkB,IAAI,CAAC;IAEpC,SAAS,CAAC,KAAa;QACrB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence-handler.d.ts","sourceRoot":"","sources":["../../src/persistence/persistence-handler.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,IAAI,MAAM,GAAG,IAAI,CAAC;CAC5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence-handler.js","sourceRoot":"","sources":["../../src/persistence/persistence-handler.ts"],"names":[],"mappings":"AAAA,+BAA+B"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export declare abstract class Profiler {
|
|
2
|
+
abstract startSection(sectionName: string): void;
|
|
3
|
+
abstract endSection(sectionName?: string): void;
|
|
4
|
+
abstract report(periodSec?: number): void;
|
|
5
|
+
}
|
|
6
|
+
export declare class NullProfiler extends Profiler {
|
|
7
|
+
startSection(_sectionName: string): void;
|
|
8
|
+
endSection(_sectionName?: string): void;
|
|
9
|
+
report(_periodSec?: number): void;
|
|
10
|
+
}
|
|
11
|
+
export declare class ProfiledSectionStats {
|
|
12
|
+
sectionName: string;
|
|
13
|
+
startTimeSec: number;
|
|
14
|
+
sampleCount: number;
|
|
15
|
+
totalTimeSec: number;
|
|
16
|
+
sampleCountBatch: number;
|
|
17
|
+
totalTimeSecBatch: number;
|
|
18
|
+
constructor(sectionName: string, startTimeSec?: number, sampleCount?: number, totalTimeSec?: number, sampleCountBatch?: number, totalTimeSecBatch?: number);
|
|
19
|
+
toString(enclosingTimeSec: number, includeBatchRates: boolean): string;
|
|
20
|
+
}
|
|
21
|
+
export declare class SimpleProfiler extends Profiler {
|
|
22
|
+
printer: (msg: string) => void;
|
|
23
|
+
enclosingSectionName: string;
|
|
24
|
+
resetAfterSampleCount: number;
|
|
25
|
+
reportSec: number;
|
|
26
|
+
sectionToStats: Map<string, ProfiledSectionStats>;
|
|
27
|
+
lastReportTimestampSec: number;
|
|
28
|
+
lastStartedSectionName: string;
|
|
29
|
+
constructor(resetAfterSampleCount?: number, enclosingSectionName?: string, printer?: (msg: string) => void, reportSec?: number);
|
|
30
|
+
startSection(sectionName: string): void;
|
|
31
|
+
endSection(name?: string): void;
|
|
32
|
+
report(periodSec?: number): void;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=simple-profiler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simple-profiler.d.ts","sourceRoot":"","sources":["../src/simple-profiler.ts"],"names":[],"mappings":"AAKA,8BAAsB,QAAQ;IAC5B,QAAQ,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAChD,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAC/C,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;CAC1C;AAED,qBAAa,YAAa,SAAQ,QAAQ;IACxC,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IACxC,UAAU,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI;IACvC,MAAM,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;CAClC;AAED,qBAAa,oBAAoB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;gBAGxB,WAAW,EAAE,MAAM,EACnB,YAAY,SAAI,EAChB,WAAW,SAAI,EACf,YAAY,SAAI,EAChB,gBAAgB,SAAI,EACpB,iBAAiB,SAAI;IAUvB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,GAAG,MAAM;CAgCvE;AAED,qBAAa,cAAe,SAAQ,QAAQ;IAC1C,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAClD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,sBAAsB,EAAE,MAAM,CAAC;gBAG7B,qBAAqB,SAAI,EACzB,oBAAoB,SAAU,EAC9B,OAAO,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAkB,EAC5C,SAAS,SAAK;IAYhB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAmBvC,UAAU,CAAC,IAAI,SAAK,GAAG,IAAI;IAkC3B,MAAM,CAAC,SAAS,SAAK,GAAG,IAAI;CAsB7B"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Based on https://github.com/davidohana/SimpleProfiler/blob/main/python/simple_profiler.py
|
|
3
|
+
import { EOL } from 'node:os';
|
|
4
|
+
export class Profiler {
|
|
5
|
+
}
|
|
6
|
+
export class NullProfiler extends Profiler {
|
|
7
|
+
startSection(_sectionName) { }
|
|
8
|
+
endSection(_sectionName) { }
|
|
9
|
+
report(_periodSec) { }
|
|
10
|
+
}
|
|
11
|
+
export class ProfiledSectionStats {
|
|
12
|
+
sectionName;
|
|
13
|
+
startTimeSec;
|
|
14
|
+
sampleCount;
|
|
15
|
+
totalTimeSec;
|
|
16
|
+
sampleCountBatch;
|
|
17
|
+
totalTimeSecBatch;
|
|
18
|
+
constructor(sectionName, startTimeSec = 0, sampleCount = 0, totalTimeSec = 0, sampleCountBatch = 0, totalTimeSecBatch = 0) {
|
|
19
|
+
this.sectionName = sectionName;
|
|
20
|
+
this.startTimeSec = startTimeSec;
|
|
21
|
+
this.sampleCount = sampleCount;
|
|
22
|
+
this.totalTimeSec = totalTimeSec;
|
|
23
|
+
this.sampleCountBatch = sampleCountBatch;
|
|
24
|
+
this.totalTimeSecBatch = totalTimeSecBatch;
|
|
25
|
+
}
|
|
26
|
+
toString(enclosingTimeSec, includeBatchRates) {
|
|
27
|
+
let tookSecText = `${this.totalTimeSec.toFixed(2).padStart(8)} s`;
|
|
28
|
+
if (enclosingTimeSec > 0) {
|
|
29
|
+
const pct = ((100 * this.totalTimeSec) / enclosingTimeSec).toFixed(2).padStart(6);
|
|
30
|
+
tookSecText += ` (${pct}%)`;
|
|
31
|
+
}
|
|
32
|
+
let msPerKSamples = ((1000000 * this.totalTimeSec) / this.sampleCount).toFixed(2).padStart(7);
|
|
33
|
+
let samplesPerSec;
|
|
34
|
+
if (this.totalTimeSec > 0) {
|
|
35
|
+
samplesPerSec = (this.sampleCount / this.totalTimeSec).toFixed(2).padStart(15);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
samplesPerSec = 'N/A';
|
|
39
|
+
}
|
|
40
|
+
if (includeBatchRates) {
|
|
41
|
+
msPerKSamples += ` (${((1000000 * this.totalTimeSecBatch) / this.sampleCountBatch).toFixed(2).padStart(7)})`;
|
|
42
|
+
if (this.totalTimeSecBatch > 0) {
|
|
43
|
+
samplesPerSec += ` (${(this.sampleCountBatch / this.totalTimeSecBatch).toFixed(2).padStart(15)})`;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
samplesPerSec += ' (N/A)';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return (`${this.sectionName.padEnd(15)}: took ${tookSecText}, ` +
|
|
50
|
+
`${this.sampleCount.toString().padStart(10)} samples, ` +
|
|
51
|
+
`${msPerKSamples} ms / 1000 samples, ` +
|
|
52
|
+
`${samplesPerSec} hz`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export class SimpleProfiler extends Profiler {
|
|
56
|
+
printer;
|
|
57
|
+
enclosingSectionName;
|
|
58
|
+
resetAfterSampleCount;
|
|
59
|
+
reportSec;
|
|
60
|
+
sectionToStats;
|
|
61
|
+
lastReportTimestampSec;
|
|
62
|
+
lastStartedSectionName;
|
|
63
|
+
constructor(resetAfterSampleCount = 0, enclosingSectionName = 'total', printer = console.log, reportSec = 30) {
|
|
64
|
+
super();
|
|
65
|
+
this.printer = printer;
|
|
66
|
+
this.enclosingSectionName = enclosingSectionName;
|
|
67
|
+
this.resetAfterSampleCount = resetAfterSampleCount;
|
|
68
|
+
this.reportSec = reportSec;
|
|
69
|
+
this.sectionToStats = new Map();
|
|
70
|
+
this.lastReportTimestampSec = Date.now() / 1000;
|
|
71
|
+
this.lastStartedSectionName = '';
|
|
72
|
+
}
|
|
73
|
+
startSection(sectionName) {
|
|
74
|
+
if (!sectionName) {
|
|
75
|
+
throw new Error('Section name is empty');
|
|
76
|
+
}
|
|
77
|
+
this.lastStartedSectionName = sectionName;
|
|
78
|
+
let section = this.sectionToStats.get(sectionName);
|
|
79
|
+
if (section === undefined) {
|
|
80
|
+
section = new ProfiledSectionStats(sectionName);
|
|
81
|
+
this.sectionToStats.set(sectionName, section);
|
|
82
|
+
}
|
|
83
|
+
if (section.startTimeSec !== 0) {
|
|
84
|
+
throw new Error(`Section ${sectionName} is already started`);
|
|
85
|
+
}
|
|
86
|
+
section.startTimeSec = Date.now() / 1000;
|
|
87
|
+
}
|
|
88
|
+
endSection(name = '') {
|
|
89
|
+
const now = Date.now() / 1000;
|
|
90
|
+
let sectionName = name;
|
|
91
|
+
if (!name) {
|
|
92
|
+
sectionName = this.lastStartedSectionName;
|
|
93
|
+
}
|
|
94
|
+
if (!sectionName) {
|
|
95
|
+
throw new Error('Neither section name is specified nor a section is started');
|
|
96
|
+
}
|
|
97
|
+
const section = this.sectionToStats.get(sectionName);
|
|
98
|
+
if (section === undefined) {
|
|
99
|
+
throw new Error(`Section ${sectionName} does not exist`);
|
|
100
|
+
}
|
|
101
|
+
if (section.startTimeSec === 0) {
|
|
102
|
+
throw new Error(`Section ${sectionName} was not started`);
|
|
103
|
+
}
|
|
104
|
+
const tookSec = now - section.startTimeSec;
|
|
105
|
+
if (this.resetAfterSampleCount > 0 && this.resetAfterSampleCount === section.sampleCount) {
|
|
106
|
+
section.sampleCountBatch = 0;
|
|
107
|
+
section.totalTimeSecBatch = 0;
|
|
108
|
+
}
|
|
109
|
+
section.sampleCount += 1;
|
|
110
|
+
section.totalTimeSec += tookSec;
|
|
111
|
+
section.sampleCountBatch += 1;
|
|
112
|
+
section.totalTimeSecBatch += tookSec;
|
|
113
|
+
section.startTimeSec = 0;
|
|
114
|
+
}
|
|
115
|
+
report(periodSec = 30) {
|
|
116
|
+
if (Date.now() / 1000 - this.lastReportTimestampSec < periodSec) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
let enclosingTimeSec = 0;
|
|
120
|
+
if (this.enclosingSectionName) {
|
|
121
|
+
const enclosing = this.sectionToStats.get(this.enclosingSectionName);
|
|
122
|
+
if (enclosing) {
|
|
123
|
+
enclosingTimeSec = enclosing.totalTimeSec;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const includeBatchRates = this.resetAfterSampleCount > 0;
|
|
127
|
+
const sections = [...this.sectionToStats.values()];
|
|
128
|
+
const sortedSections = sections.sort((a, b) => b.totalTimeSec - a.totalTimeSec);
|
|
129
|
+
const lines = sortedSections.map((s) => s.toString(enclosingTimeSec, includeBatchRates));
|
|
130
|
+
const text = lines.join(EOL);
|
|
131
|
+
this.printer(text);
|
|
132
|
+
this.lastReportTimestampSec = Date.now() / 1000;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=simple-profiler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simple-profiler.js","sourceRoot":"","sources":["../src/simple-profiler.ts"],"names":[],"mappings":"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"}
|