@wener/common 2.0.5 → 2.0.6

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 (206) hide show
  1. package/lib/ai/qwen3vl/index.js +1 -1
  2. package/lib/ai/qwen3vl/utils.js +15 -15
  3. package/lib/ai/vision/DocLayoutElementTypeSchema.js +22 -22
  4. package/lib/ai/vision/ImageAnnotationSchema.js +63 -47
  5. package/lib/ai/vision/index.js +2 -2
  6. package/lib/ai/vision/resolveImageAnnotation.js +81 -95
  7. package/lib/cn/ChineseResidentIdNo.js +55 -41
  8. package/lib/cn/ChineseResidentIdNo.mod.js +6 -1
  9. package/lib/cn/ChineseResidentIdNo.test.js +22 -21
  10. package/lib/cn/DivisionCode.js +220 -235
  11. package/lib/cn/DivisionCode.mod.js +6 -1
  12. package/lib/cn/DivisionCode.test.js +92 -121
  13. package/lib/cn/Mod11.js +18 -37
  14. package/lib/cn/Mod31.js +23 -41
  15. package/lib/cn/UnifiedSocialCreditCode.js +143 -137
  16. package/lib/cn/UnifiedSocialCreditCode.mod.js +6 -1
  17. package/lib/cn/UnifiedSocialCreditCode.test.js +21 -15
  18. package/lib/cn/formatChineseAmount.js +46 -71
  19. package/lib/cn/index.js +6 -6
  20. package/lib/cn/mod.js +5 -3
  21. package/lib/cn/parseChineseNumber.js +81 -85
  22. package/lib/cn/parseChineseNumber.test.js +183 -261
  23. package/lib/cn/pinyin/cartesianProduct.js +19 -19
  24. package/lib/cn/pinyin/cartesianProduct.test.js +78 -178
  25. package/lib/cn/pinyin/loader.js +13 -11
  26. package/lib/cn/pinyin/preload.js +2 -1
  27. package/lib/cn/pinyin/toPinyin.test.js +149 -161
  28. package/lib/cn/pinyin/toPinyinPure.js +28 -23
  29. package/lib/cn/pinyin/transform.js +11 -11
  30. package/lib/cn/types.d.js +2 -2
  31. package/lib/consola/createStandardConsolaReporter.js +14 -15
  32. package/lib/consola/formatLogObject.js +149 -133
  33. package/lib/consola/formatLogObject.test.js +167 -178
  34. package/lib/consola/index.js +2 -2
  35. package/lib/data/formatSort.js +14 -12
  36. package/lib/data/formatSort.test.js +33 -33
  37. package/lib/data/index.js +3 -3
  38. package/lib/data/maybeNumber.js +23 -23
  39. package/lib/data/parseSort.js +75 -68
  40. package/lib/data/parseSort.test.js +196 -187
  41. package/lib/data/resolvePagination.js +38 -39
  42. package/lib/data/resolvePagination.test.js +228 -218
  43. package/lib/data/types.d.js +2 -2
  44. package/lib/dayjs/dayjs.js +20 -20
  45. package/lib/dayjs/formatDuration.js +56 -56
  46. package/lib/dayjs/formatDuration.test.js +63 -77
  47. package/lib/dayjs/index.js +4 -4
  48. package/lib/dayjs/parseDuration.js +21 -26
  49. package/lib/dayjs/parseRelativeTime.js +65 -66
  50. package/lib/dayjs/parseRelativeTime.test.js +227 -243
  51. package/lib/dayjs/resolveRelativeTime.js +73 -72
  52. package/lib/dayjs/resolveRelativeTime.test.js +296 -307
  53. package/lib/decimal/index.js +1 -1
  54. package/lib/decimal/parseDecimal.js +12 -12
  55. package/lib/drain3/Drain.js +303 -338
  56. package/lib/drain3/LogCluster.js +25 -25
  57. package/lib/drain3/Node.js +24 -24
  58. package/lib/drain3/TemplateMiner.js +197 -196
  59. package/lib/drain3/index.js +5 -5
  60. package/lib/drain3/persistence/FilePersistence.js +19 -19
  61. package/lib/drain3/persistence/MemoryPersistence.js +8 -8
  62. package/lib/drain3/persistence/PersistenceHandler.js +2 -2
  63. package/lib/drain3/types.js +2 -2
  64. package/lib/emittery/emitter.js +7 -7
  65. package/lib/emittery/index.js +1 -1
  66. package/lib/foundation/schema/SexType.js +15 -12
  67. package/lib/foundation/schema/index.js +1 -1
  68. package/lib/foundation/schema/parseSexType.js +15 -16
  69. package/lib/foundation/schema/types.js +8 -6
  70. package/lib/fs/FileSystemError.js +18 -18
  71. package/lib/fs/IFileSystem.d.js +2 -2
  72. package/lib/fs/MemoryFileSystem.test.js +172 -181
  73. package/lib/fs/createBrowserFileSystem.js +222 -235
  74. package/lib/fs/createMemoryFileSystem.js +472 -510
  75. package/lib/fs/createSandboxFileSystem.js +102 -101
  76. package/lib/fs/createWebDavFileSystem.js +162 -149
  77. package/lib/fs/createWebFileSystem.js +197 -220
  78. package/lib/fs/findMimeType.js +14 -14
  79. package/lib/fs/index.js +7 -7
  80. package/lib/fs/minio/createMinioFileSystem.js +959 -956
  81. package/lib/fs/minio/index.js +1 -1
  82. package/lib/fs/orpc/FileSystemContract.js +57 -57
  83. package/lib/fs/orpc/createContractClientFileSystem.js +88 -88
  84. package/lib/fs/orpc/index.js +2 -2
  85. package/lib/fs/orpc/server/createFileSystemContractImpl.js +62 -60
  86. package/lib/fs/orpc/server/index.js +1 -1
  87. package/lib/fs/s3/createS3MiniFileSystem.js +756 -737
  88. package/lib/fs/s3/index.js +1 -1
  89. package/lib/fs/s3/s3mini.test.js +524 -553
  90. package/lib/fs/scandir.js +56 -56
  91. package/lib/fs/server/createDatabaseFileSystem.js +834 -741
  92. package/lib/fs/server/createNodeFileSystem.js +407 -405
  93. package/lib/fs/server/dbfs.test.js +201 -214
  94. package/lib/fs/server/index.js +1 -1
  95. package/lib/fs/server/loadTestDatabase.js +40 -43
  96. package/lib/fs/tests/runFileSystemTest.js +352 -316
  97. package/lib/fs/types.js +17 -20
  98. package/lib/fs/utils/getFileUrl.js +24 -30
  99. package/lib/fs/utils.js +17 -17
  100. package/lib/fs/webdav/index.js +1 -1
  101. package/lib/index.js +2 -2
  102. package/lib/jsonschema/JsonSchema.js +216 -155
  103. package/lib/jsonschema/JsonSchema.test.js +123 -124
  104. package/lib/jsonschema/forEachJsonSchema.js +41 -41
  105. package/lib/jsonschema/index.js +2 -2
  106. package/lib/jsonschema/types.d.js +2 -2
  107. package/lib/meta/defineFileType.js +32 -38
  108. package/lib/meta/defineInit.js +39 -35
  109. package/lib/meta/defineMetadata.js +37 -34
  110. package/lib/meta/defineMetadata.test.js +13 -12
  111. package/lib/meta/index.js +3 -3
  112. package/lib/orpc/createOpenApiContractClient.js +26 -24
  113. package/lib/orpc/createRpcContractClient.js +37 -31
  114. package/lib/orpc/index.js +2 -2
  115. package/lib/orpc/resolveLinkPlugins.js +25 -25
  116. package/lib/password/PHC.js +187 -189
  117. package/lib/password/PHC.test.js +517 -535
  118. package/lib/password/Password.js +85 -80
  119. package/lib/password/Password.test.js +330 -364
  120. package/lib/password/createArgon2PasswordAlgorithm.js +50 -51
  121. package/lib/password/createBase64PasswordAlgorithm.js +11 -11
  122. package/lib/password/createBcryptPasswordAlgorithm.js +20 -18
  123. package/lib/password/createPBKDF2PasswordAlgorithm.js +65 -52
  124. package/lib/password/createScryptPasswordAlgorithm.js +74 -63
  125. package/lib/password/index.js +5 -5
  126. package/lib/password/server/index.js +1 -1
  127. package/lib/resource/Identifiable.js +2 -2
  128. package/lib/resource/ListQuery.js +42 -42
  129. package/lib/resource/getTitleOfResource.js +5 -5
  130. package/lib/resource/index.js +2 -2
  131. package/lib/resource/schema/AnyResourceSchema.js +91 -89
  132. package/lib/resource/schema/BaseResourceSchema.js +26 -26
  133. package/lib/resource/schema/ResourceActionType.js +117 -115
  134. package/lib/resource/schema/ResourceStatus.js +94 -92
  135. package/lib/resource/schema/ResourceType.js +25 -23
  136. package/lib/resource/schema/index.js +5 -5
  137. package/lib/resource/schema/types.js +86 -55
  138. package/lib/resource/schema/types.test.js +16 -13
  139. package/lib/s3/formatS3Url.js +60 -60
  140. package/lib/s3/formatS3Url.test.js +238 -261
  141. package/lib/s3/index.js +2 -2
  142. package/lib/s3/parseS3Url.js +61 -60
  143. package/lib/s3/parseS3Url.test.js +270 -269
  144. package/lib/schema/SchemaRegistry.js +41 -42
  145. package/lib/schema/SchemaRegistry.mod.js +1 -1
  146. package/lib/schema/TypeSchema.d.js +2 -2
  147. package/lib/schema/createSchemaData.js +113 -67
  148. package/lib/schema/findJsonSchemaByPath.js +28 -23
  149. package/lib/schema/formatZodError.js +112 -131
  150. package/lib/schema/formatZodError.test.js +192 -195
  151. package/lib/schema/getSchemaCache.js +7 -7
  152. package/lib/schema/getSchemaOptions.js +17 -16
  153. package/lib/schema/index.js +6 -6
  154. package/lib/schema/toJsonSchema.js +195 -189
  155. package/lib/schema/toJsonSchema.test.js +34 -26
  156. package/lib/schema/validate.js +105 -96
  157. package/lib/tools/generateSchema.js +40 -40
  158. package/lib/tools/renderJsonSchemaToMarkdownDoc.js +74 -74
  159. package/lib/utils/buildBaseUrl.js +8 -8
  160. package/lib/utils/buildRedactorFormSchema.js +54 -53
  161. package/lib/utils/getEstimateProcessTime.js +24 -19
  162. package/lib/utils/index.js +3 -3
  163. package/lib/utils/resolveFeatureOptions.js +9 -9
  164. package/package.json +14 -14
  165. package/src/ai/vision/index.ts +2 -2
  166. package/src/cn/index.ts +1 -2
  167. package/src/consola/index.ts +1 -1
  168. package/src/data/index.ts +3 -4
  169. package/src/data/resolvePagination.ts +2 -2
  170. package/src/dayjs/formatDuration.ts +8 -9
  171. package/src/dayjs/index.ts +1 -1
  172. package/src/dayjs/parseRelativeTime.ts +1 -1
  173. package/src/dayjs/resolveRelativeTime.ts +1 -1
  174. package/src/drain3/Drain.test.ts +2 -2
  175. package/src/drain3/index.ts +2 -4
  176. package/src/fs/createWebDavFileSystem.ts +2 -7
  177. package/src/fs/createWebFileSystem.ts +1 -1
  178. package/src/fs/index.ts +4 -4
  179. package/src/fs/minio/createMinioFileSystem.ts +2 -2
  180. package/src/fs/minio/index.ts +1 -1
  181. package/src/fs/s3/createS3MiniFileSystem.ts +1 -1
  182. package/src/fs/server/createDatabaseFileSystem.ts +84 -120
  183. package/src/fs/server/dbfs.test.ts +14 -10
  184. package/src/fs/server/index.ts +1 -0
  185. package/src/fs/server/loadTestDatabase.ts +8 -119
  186. package/src/jsonschema/index.ts +1 -1
  187. package/src/meta/index.ts +2 -3
  188. package/src/orm/createSqliteDialect.ts +17 -0
  189. package/src/orm/index.ts +1 -0
  190. package/src/orpc/createOpenApiContractClient.ts +1 -1
  191. package/src/orpc/index.ts +1 -1
  192. package/src/password/createArgon2PasswordAlgorithm.ts +1 -1
  193. package/src/password/index.ts +2 -2
  194. package/src/resource/index.ts +3 -3
  195. package/src/resource/schema/index.ts +4 -4
  196. package/src/s3/index.ts +1 -1
  197. package/src/schema/SchemaRegistry.ts +1 -1
  198. package/src/schema/createSchemaData.ts +1 -1
  199. package/src/schema/findJsonSchemaByPath.ts +1 -1
  200. package/src/schema/index.ts +5 -5
  201. package/src/schema/validate.ts +1 -1
  202. package/src/utils/buildRedactorFormSchema.ts +1 -1
  203. package/src/utils/formatNumber.ts +18 -0
  204. package/src/utils/formatPercent.ts +17 -0
  205. package/src/utils/index.ts +3 -3
  206. package/src/utils/resolveFeatureOptions.ts +1 -1
@@ -1,51 +1,49 @@
1
- import { LogCluster } from "./LogCluster.js";
2
- import { Node } from "./Node.js";
1
+ import { LogCluster } from './LogCluster.js';
2
+ import { Node } from './Node.js';
3
+
3
4
  /**
4
5
  * Simple LRU cache using Map iteration order.
5
6
  * Map preserves insertion order; re-inserting a key moves it to the end.
6
7
  */ let SimpleLRU = class SimpleLRU {
7
- max;
8
- map = new Map();
9
- constructor(max) {
10
- this.max = max;
11
- }
12
- get(key) {
13
- const value = this.map.get(key);
14
- if (value !== undefined) {
15
- // Move to end (most recently used)
16
- this.map.delete(key);
17
- this.map.set(key, value);
18
- }
19
- return value;
20
- }
21
- set(key, value) {
22
- if (this.map.has(key)) {
23
- this.map.delete(key);
24
- }
25
- else if (this.map.size >= this.max) {
26
- // Evict oldest (first key)
27
- const first = this.map.keys().next().value;
28
- if (first !== undefined) {
29
- this.map.delete(first);
30
- }
31
- }
32
- this.map.set(key, value);
33
- }
34
- values() {
35
- return this.map.values();
36
- }
8
+ max;
9
+ map = new Map();
10
+ constructor(max) {
11
+ this.max = max;
12
+ }
13
+ get(key) {
14
+ const value = this.map.get(key);
15
+ if (value !== undefined) {
16
+ // Move to end (most recently used)
17
+ this.map.delete(key);
18
+ this.map.set(key, value);
19
+ }
20
+ return value;
21
+ }
22
+ set(key, value) {
23
+ if (this.map.has(key)) {
24
+ this.map.delete(key);
25
+ } else if (this.map.size >= this.max) {
26
+ // Evict oldest (first key)
27
+ const first = this.map.keys().next().value;
28
+ if (first !== undefined) {
29
+ this.map.delete(first);
30
+ }
31
+ }
32
+ this.map.set(key, value);
33
+ }
34
+ values() {
35
+ return this.map.values();
36
+ }
37
37
  };
38
38
  function isSliceEqual(a, b) {
39
- if (a.length !== b.length)
40
- return false;
41
- for (let i = 0; i < a.length; i++) {
42
- if (a[i] !== b[i])
43
- return false;
44
- }
45
- return true;
39
+ if (a.length !== b.length) return false;
40
+ for (let i = 0; i < a.length; i++) {
41
+ if (a[i] !== b[i]) return false;
42
+ }
43
+ return true;
46
44
  }
47
45
  function hasNumbers(s) {
48
- return /\d/.test(s);
46
+ return /\d/.test(s);
49
47
  }
50
48
  /**
51
49
  * Core Drain algorithm for log clustering.
@@ -54,303 +52,270 @@ function hasNumbers(s) {
54
52
  * based on their structural similarity, extracting templates by parameterizing
55
53
  * variable parts of the logs.
56
54
  */ export class Drain {
57
- logClusterDepth;
58
- maxNodeDepth;
59
- simTh;
60
- maxChildren;
61
- rootNode;
62
- maxClusters;
63
- extraDelimiters;
64
- paramStr;
65
- parametrizeNumericTokens;
66
- idToCluster;
67
- clustersCounter = 0;
68
- constructor(options = {}) {
69
- this.logClusterDepth = options.logClusterDepth ?? 4;
70
- this.simTh = options.simTh ?? 0.4;
71
- this.maxChildren = options.maxChildren ?? 100;
72
- this.maxClusters = options.maxClusters ?? 1000;
73
- this.extraDelimiters = options.extraDelimiters ?? [];
74
- this.paramStr = options.paramStr ?? "<*>";
75
- this.parametrizeNumericTokens = options.parametrizeNumericTokens ?? true;
76
- if (this.logClusterDepth < 3) {
77
- throw new Error("depth argument must be at least 3");
78
- }
79
- this.maxNodeDepth = this.logClusterDepth - 2;
80
- this.rootNode = Node.newNode();
81
- this.idToCluster = new SimpleLRU(this.maxClusters);
82
- }
83
- addLogMessage(content) {
84
- const contentTokens = this.getContentAsTokens(content);
85
- const matchCluster = this.treeSearch(this.rootNode, contentTokens, this.simTh, false);
86
- let updateType = "none";
87
- if (matchCluster === null) {
88
- this.clustersCounter++;
89
- const clusterId = this.clustersCounter;
90
- const cluster = new LogCluster(clusterId, contentTokens);
91
- this.idToCluster.set(clusterId, cluster);
92
- this.addSeqToPrefixTree(this.rootNode, cluster);
93
- updateType = "created";
94
- return {
95
- cluster,
96
- updateType
97
- };
98
- }
99
- const newTemplateTokens = this.createTemplate(contentTokens, matchCluster.logTemplateTokens);
100
- if (!isSliceEqual(newTemplateTokens, matchCluster.logTemplateTokens)) {
101
- matchCluster.logTemplateTokens = newTemplateTokens;
102
- updateType = "templateChanged";
103
- }
104
- matchCluster.size++;
105
- // Touch cluster to update its position in the LRU cache
106
- this.idToCluster.get(matchCluster.clusterId);
107
- return {
108
- cluster: matchCluster,
109
- updateType
110
- };
111
- }
112
- getContentAsTokens(content) {
113
- let processed = content.trim();
114
- for (const delimiter of this.extraDelimiters) {
115
- processed = processed.replaceAll(delimiter, " ");
116
- }
117
- return processed.split(/\s+/).filter((token) => token.length > 0);
118
- }
119
- treeSearch(rootNode, tokens, simTh, includeParams) {
120
- const tokenCount = tokens.length;
121
- const firstNode = rootNode.keyToChildNode.get(tokenCount.toString());
122
- if (firstNode === undefined)
123
- return null;
124
- if (tokenCount === 0) {
125
- const firstClusterId = firstNode.clusterIds[0];
126
- if (firstClusterId === undefined)
127
- return null;
128
- return this.idToCluster.get(firstClusterId) ?? null;
129
- }
130
- let currentNode = firstNode;
131
- let currentNodeDepth = 1;
132
- for (const token of tokens) {
133
- if (currentNodeDepth >= this.maxNodeDepth || currentNodeDepth === tokenCount)
134
- break;
135
- const keyToChildNode = currentNode.keyToChildNode;
136
- let nextNode = keyToChildNode.get(token);
137
- if (nextNode === undefined) {
138
- nextNode = keyToChildNode.get(this.paramStr);
139
- }
140
- if (nextNode === undefined)
141
- return null;
142
- currentNode = nextNode;
143
- currentNodeDepth += 1;
144
- }
145
- return this.fastMatch(currentNode.clusterIds, tokens, simTh, includeParams);
146
- }
147
- fastMatch(clusterIds, tokens, simTh, includeParams) {
148
- let maxSim = -1;
149
- let maxParamCount = -1;
150
- let maxCluster = null;
151
- for (const clusterId of clusterIds) {
152
- const cluster = this.idToCluster.get(clusterId);
153
- if (cluster === undefined)
154
- continue;
155
- const [currentSim, paramCount] = this.getSeqDistance(cluster.logTemplateTokens, tokens, includeParams);
156
- if (currentSim > maxSim || currentSim === maxSim && paramCount > maxParamCount) {
157
- maxSim = currentSim;
158
- maxParamCount = paramCount;
159
- maxCluster = cluster;
160
- }
161
- }
162
- return maxSim >= simTh ? maxCluster : null;
163
- }
164
- getSeqDistance(seq1, seq2, includeParams) {
165
- if (seq1.length !== seq2.length) {
166
- throw new Error(`seq1 length ${seq1.length} not equals to seq2 length ${seq2.length}`);
167
- }
168
- if (seq1.length === 0)
169
- return [
170
- 1,
171
- 0
172
- ];
173
- let simTokens = 0;
174
- let paramCount = 0;
175
- for (let i = 0; i < seq1.length; i++) {
176
- if (seq1[i] === this.paramStr) {
177
- paramCount++;
178
- }
179
- else if (seq1[i] === seq2[i]) {
180
- simTokens++;
181
- }
182
- }
183
- if (includeParams)
184
- simTokens += paramCount;
185
- return [
186
- simTokens / seq1.length,
187
- paramCount
188
- ];
189
- }
190
- addSeqToPrefixTree(rootNode, cluster) {
191
- const tokenCount = cluster.logTemplateTokens.length;
192
- const tokenCountStr = tokenCount.toString();
193
- let firstLayerNode = rootNode.keyToChildNode.get(tokenCountStr);
194
- if (firstLayerNode === undefined) {
195
- firstLayerNode = Node.newNode();
196
- rootNode.keyToChildNode.set(tokenCountStr, firstLayerNode);
197
- }
198
- let currentNode = firstLayerNode;
199
- if (tokenCount === 0) {
200
- currentNode.clusterIds = [
201
- cluster.clusterId
202
- ];
203
- return;
204
- }
205
- let currentDepth = 1;
206
- for (const token of cluster.logTemplateTokens) {
207
- if (currentDepth >= this.maxNodeDepth || currentDepth >= tokenCount) {
208
- const newClusterIds = [];
209
- for (const clusterId of currentNode.clusterIds) {
210
- if (this.idToCluster.get(clusterId) !== undefined) {
211
- newClusterIds.push(clusterId);
212
- }
213
- }
214
- newClusterIds.push(cluster.clusterId);
215
- currentNode.clusterIds = newClusterIds;
216
- break;
217
- }
218
- if (!currentNode.keyToChildNode.has(token)) {
219
- if (this.parametrizeNumericTokens && hasNumbers(token)) {
220
- const node = currentNode.keyToChildNode.get(this.paramStr);
221
- if (node === undefined) {
222
- const newNode = Node.newNode();
223
- currentNode.keyToChildNode.set(this.paramStr, newNode);
224
- currentNode = newNode;
225
- }
226
- else {
227
- currentNode = node;
228
- }
229
- }
230
- else {
231
- const wildcardNode = currentNode.keyToChildNode.get(this.paramStr);
232
- if (wildcardNode !== undefined) {
233
- if (currentNode.keyToChildNode.size < this.maxChildren) {
234
- const newNode = Node.newNode();
235
- currentNode.keyToChildNode.set(token, newNode);
236
- currentNode = newNode;
237
- }
238
- else {
239
- currentNode = wildcardNode;
240
- }
241
- }
242
- else {
243
- if (currentNode.keyToChildNode.size + 1 < this.maxChildren) {
244
- const newNode = Node.newNode();
245
- currentNode.keyToChildNode.set(token, newNode);
246
- currentNode = newNode;
247
- }
248
- else if (currentNode.keyToChildNode.size + 1 === this.maxChildren) {
249
- const newNode = Node.newNode();
250
- currentNode.keyToChildNode.set(this.paramStr, newNode);
251
- currentNode = newNode;
252
- }
253
- else {
254
- currentNode = currentNode.keyToChildNode.get(this.paramStr);
255
- }
256
- }
257
- }
258
- }
259
- else {
260
- currentNode = currentNode.keyToChildNode.get(token);
261
- }
262
- currentDepth++;
263
- }
264
- }
265
- createTemplate(seq1, seq2) {
266
- if (seq1.length !== seq2.length) {
267
- throw new Error(`seq1 length ${seq1.length} not equals to seq2 length ${seq2.length}`);
268
- }
269
- const retVal = [
270
- ...seq2
271
- ];
272
- for (let i = 0; i < seq1.length; i++) {
273
- if (seq1[i] !== seq2[i]) {
274
- retVal[i] = this.paramStr;
275
- }
276
- }
277
- return retVal;
278
- }
279
- match(content, strategy = "never") {
280
- const requiredSimTh = 1;
281
- const contentTokens = this.getContentAsTokens(content);
282
- const fullSearch = () => {
283
- const allIds = this.getClustersIdsForSeqLen(contentTokens.length);
284
- return this.fastMatch(allIds, contentTokens, requiredSimTh, true);
285
- };
286
- if (strategy === "always")
287
- return fullSearch();
288
- const matchCluster = this.treeSearch(this.rootNode, contentTokens, requiredSimTh, true);
289
- if (matchCluster !== null)
290
- return matchCluster;
291
- if (strategy === "never")
292
- return null;
293
- return fullSearch();
294
- }
295
- getClustersIdsForSeqLen(seqLen) {
296
- const appendClusterRecursive = (node, idListToFill) => {
297
- idListToFill.push(...node.clusterIds);
298
- for (const childNode of node.keyToChildNode.values()) {
299
- appendClusterRecursive(childNode, idListToFill);
300
- }
301
- };
302
- const currentNode = this.rootNode.keyToChildNode.get(seqLen.toString());
303
- if (currentNode === undefined)
304
- return [];
305
- const target = [];
306
- appendClusterRecursive(currentNode, target);
307
- return target;
308
- }
309
- getClusters() {
310
- return [
311
- ...this.idToCluster.values()
312
- ];
313
- }
314
- toJSON() {
315
- return {
316
- logClusterDepth: this.logClusterDepth,
317
- maxNodeDepth: this.maxNodeDepth,
318
- simTh: this.simTh,
319
- maxChildren: this.maxChildren,
320
- rootNode: this.rootNode.toJSON(),
321
- maxClusters: this.maxClusters,
322
- extraDelimiters: [
323
- ...this.extraDelimiters
324
- ],
325
- paramStr: this.paramStr,
326
- parametrizeNumericTokens: this.parametrizeNumericTokens,
327
- clusters: this.getClusters().map((c) => c.toJSON()),
328
- clustersCounter: this.clustersCounter
329
- };
330
- }
331
- static fromJSON(data) {
332
- const drain = new Drain({
333
- logClusterDepth: data.logClusterDepth,
334
- simTh: data.simTh,
335
- maxChildren: data.maxChildren,
336
- maxClusters: data.maxClusters,
337
- extraDelimiters: data.extraDelimiters,
338
- paramStr: data.paramStr,
339
- parametrizeNumericTokens: data.parametrizeNumericTokens
340
- });
341
- drain.rootNode.keyToChildNode.clear();
342
- drain.rootNode.clusterIds = [];
343
- const rootNode = Node.fromJSON(data.rootNode);
344
- for (const [key, node] of rootNode.keyToChildNode) {
345
- drain.rootNode.keyToChildNode.set(key, node);
346
- }
347
- drain.rootNode.clusterIds = rootNode.clusterIds;
348
- for (const clusterData of data.clusters) {
349
- const cluster = LogCluster.fromJSON(clusterData);
350
- drain.idToCluster.set(cluster.clusterId, cluster);
351
- }
352
- drain.clustersCounter = data.clustersCounter;
353
- return drain;
354
- }
55
+ logClusterDepth;
56
+ maxNodeDepth;
57
+ simTh;
58
+ maxChildren;
59
+ rootNode;
60
+ maxClusters;
61
+ extraDelimiters;
62
+ paramStr;
63
+ parametrizeNumericTokens;
64
+ idToCluster;
65
+ clustersCounter = 0;
66
+ constructor(options = {}) {
67
+ this.logClusterDepth = options.logClusterDepth ?? 4;
68
+ this.simTh = options.simTh ?? 0.4;
69
+ this.maxChildren = options.maxChildren ?? 100;
70
+ this.maxClusters = options.maxClusters ?? 1000;
71
+ this.extraDelimiters = options.extraDelimiters ?? [];
72
+ this.paramStr = options.paramStr ?? '<*>';
73
+ this.parametrizeNumericTokens = options.parametrizeNumericTokens ?? true;
74
+ if (this.logClusterDepth < 3) {
75
+ throw new Error('depth argument must be at least 3');
76
+ }
77
+ this.maxNodeDepth = this.logClusterDepth - 2;
78
+ this.rootNode = Node.newNode();
79
+ this.idToCluster = new SimpleLRU(this.maxClusters);
80
+ }
81
+ addLogMessage(content) {
82
+ const contentTokens = this.getContentAsTokens(content);
83
+ const matchCluster = this.treeSearch(this.rootNode, contentTokens, this.simTh, false);
84
+ let updateType = 'none';
85
+ if (matchCluster === null) {
86
+ this.clustersCounter++;
87
+ const clusterId = this.clustersCounter;
88
+ const cluster = new LogCluster(clusterId, contentTokens);
89
+ this.idToCluster.set(clusterId, cluster);
90
+ this.addSeqToPrefixTree(this.rootNode, cluster);
91
+ updateType = 'created';
92
+ return {
93
+ cluster,
94
+ updateType,
95
+ };
96
+ }
97
+ const newTemplateTokens = this.createTemplate(contentTokens, matchCluster.logTemplateTokens);
98
+ if (!isSliceEqual(newTemplateTokens, matchCluster.logTemplateTokens)) {
99
+ matchCluster.logTemplateTokens = newTemplateTokens;
100
+ updateType = 'templateChanged';
101
+ }
102
+ matchCluster.size++;
103
+ // Touch cluster to update its position in the LRU cache
104
+ this.idToCluster.get(matchCluster.clusterId);
105
+ return {
106
+ cluster: matchCluster,
107
+ updateType,
108
+ };
109
+ }
110
+ getContentAsTokens(content) {
111
+ let processed = content.trim();
112
+ for (const delimiter of this.extraDelimiters) {
113
+ processed = processed.replaceAll(delimiter, ' ');
114
+ }
115
+ return processed.split(/\s+/).filter((token) => token.length > 0);
116
+ }
117
+ treeSearch(rootNode, tokens, simTh, includeParams) {
118
+ const tokenCount = tokens.length;
119
+ const firstNode = rootNode.keyToChildNode.get(tokenCount.toString());
120
+ if (firstNode === undefined) return null;
121
+ if (tokenCount === 0) {
122
+ const firstClusterId = firstNode.clusterIds[0];
123
+ if (firstClusterId === undefined) return null;
124
+ return this.idToCluster.get(firstClusterId) ?? null;
125
+ }
126
+ let currentNode = firstNode;
127
+ let currentNodeDepth = 1;
128
+ for (const token of tokens) {
129
+ if (currentNodeDepth >= this.maxNodeDepth || currentNodeDepth === tokenCount) break;
130
+ const keyToChildNode = currentNode.keyToChildNode;
131
+ let nextNode = keyToChildNode.get(token);
132
+ if (nextNode === undefined) {
133
+ nextNode = keyToChildNode.get(this.paramStr);
134
+ }
135
+ if (nextNode === undefined) return null;
136
+ currentNode = nextNode;
137
+ currentNodeDepth += 1;
138
+ }
139
+ return this.fastMatch(currentNode.clusterIds, tokens, simTh, includeParams);
140
+ }
141
+ fastMatch(clusterIds, tokens, simTh, includeParams) {
142
+ let maxSim = -1;
143
+ let maxParamCount = -1;
144
+ let maxCluster = null;
145
+ for (const clusterId of clusterIds) {
146
+ const cluster = this.idToCluster.get(clusterId);
147
+ if (cluster === undefined) continue;
148
+ const [currentSim, paramCount] = this.getSeqDistance(cluster.logTemplateTokens, tokens, includeParams);
149
+ if (currentSim > maxSim || (currentSim === maxSim && paramCount > maxParamCount)) {
150
+ maxSim = currentSim;
151
+ maxParamCount = paramCount;
152
+ maxCluster = cluster;
153
+ }
154
+ }
155
+ return maxSim >= simTh ? maxCluster : null;
156
+ }
157
+ getSeqDistance(seq1, seq2, includeParams) {
158
+ if (seq1.length !== seq2.length) {
159
+ throw new Error(`seq1 length ${seq1.length} not equals to seq2 length ${seq2.length}`);
160
+ }
161
+ if (seq1.length === 0) return [1, 0];
162
+ let simTokens = 0;
163
+ let paramCount = 0;
164
+ for (let i = 0; i < seq1.length; i++) {
165
+ if (seq1[i] === this.paramStr) {
166
+ paramCount++;
167
+ } else if (seq1[i] === seq2[i]) {
168
+ simTokens++;
169
+ }
170
+ }
171
+ if (includeParams) simTokens += paramCount;
172
+ return [simTokens / seq1.length, paramCount];
173
+ }
174
+ addSeqToPrefixTree(rootNode, cluster) {
175
+ const tokenCount = cluster.logTemplateTokens.length;
176
+ const tokenCountStr = tokenCount.toString();
177
+ let firstLayerNode = rootNode.keyToChildNode.get(tokenCountStr);
178
+ if (firstLayerNode === undefined) {
179
+ firstLayerNode = Node.newNode();
180
+ rootNode.keyToChildNode.set(tokenCountStr, firstLayerNode);
181
+ }
182
+ let currentNode = firstLayerNode;
183
+ if (tokenCount === 0) {
184
+ currentNode.clusterIds = [cluster.clusterId];
185
+ return;
186
+ }
187
+ let currentDepth = 1;
188
+ for (const token of cluster.logTemplateTokens) {
189
+ if (currentDepth >= this.maxNodeDepth || currentDepth >= tokenCount) {
190
+ const newClusterIds = [];
191
+ for (const clusterId of currentNode.clusterIds) {
192
+ if (this.idToCluster.get(clusterId) !== undefined) {
193
+ newClusterIds.push(clusterId);
194
+ }
195
+ }
196
+ newClusterIds.push(cluster.clusterId);
197
+ currentNode.clusterIds = newClusterIds;
198
+ break;
199
+ }
200
+ if (!currentNode.keyToChildNode.has(token)) {
201
+ if (this.parametrizeNumericTokens && hasNumbers(token)) {
202
+ const node = currentNode.keyToChildNode.get(this.paramStr);
203
+ if (node === undefined) {
204
+ const newNode = Node.newNode();
205
+ currentNode.keyToChildNode.set(this.paramStr, newNode);
206
+ currentNode = newNode;
207
+ } else {
208
+ currentNode = node;
209
+ }
210
+ } else {
211
+ const wildcardNode = currentNode.keyToChildNode.get(this.paramStr);
212
+ if (wildcardNode !== undefined) {
213
+ if (currentNode.keyToChildNode.size < this.maxChildren) {
214
+ const newNode = Node.newNode();
215
+ currentNode.keyToChildNode.set(token, newNode);
216
+ currentNode = newNode;
217
+ } else {
218
+ currentNode = wildcardNode;
219
+ }
220
+ } else {
221
+ if (currentNode.keyToChildNode.size + 1 < this.maxChildren) {
222
+ const newNode = Node.newNode();
223
+ currentNode.keyToChildNode.set(token, newNode);
224
+ currentNode = newNode;
225
+ } else if (currentNode.keyToChildNode.size + 1 === this.maxChildren) {
226
+ const newNode = Node.newNode();
227
+ currentNode.keyToChildNode.set(this.paramStr, newNode);
228
+ currentNode = newNode;
229
+ } else {
230
+ currentNode = currentNode.keyToChildNode.get(this.paramStr);
231
+ }
232
+ }
233
+ }
234
+ } else {
235
+ currentNode = currentNode.keyToChildNode.get(token);
236
+ }
237
+ currentDepth++;
238
+ }
239
+ }
240
+ createTemplate(seq1, seq2) {
241
+ if (seq1.length !== seq2.length) {
242
+ throw new Error(`seq1 length ${seq1.length} not equals to seq2 length ${seq2.length}`);
243
+ }
244
+ const retVal = [...seq2];
245
+ for (let i = 0; i < seq1.length; i++) {
246
+ if (seq1[i] !== seq2[i]) {
247
+ retVal[i] = this.paramStr;
248
+ }
249
+ }
250
+ return retVal;
251
+ }
252
+ match(content, strategy = 'never') {
253
+ const requiredSimTh = 1;
254
+ const contentTokens = this.getContentAsTokens(content);
255
+ const fullSearch = () => {
256
+ const allIds = this.getClustersIdsForSeqLen(contentTokens.length);
257
+ return this.fastMatch(allIds, contentTokens, requiredSimTh, true);
258
+ };
259
+ if (strategy === 'always') return fullSearch();
260
+ const matchCluster = this.treeSearch(this.rootNode, contentTokens, requiredSimTh, true);
261
+ if (matchCluster !== null) return matchCluster;
262
+ if (strategy === 'never') return null;
263
+ return fullSearch();
264
+ }
265
+ getClustersIdsForSeqLen(seqLen) {
266
+ const appendClusterRecursive = (node, idListToFill) => {
267
+ idListToFill.push(...node.clusterIds);
268
+ for (const childNode of node.keyToChildNode.values()) {
269
+ appendClusterRecursive(childNode, idListToFill);
270
+ }
271
+ };
272
+ const currentNode = this.rootNode.keyToChildNode.get(seqLen.toString());
273
+ if (currentNode === undefined) return [];
274
+ const target = [];
275
+ appendClusterRecursive(currentNode, target);
276
+ return target;
277
+ }
278
+ getClusters() {
279
+ return [...this.idToCluster.values()];
280
+ }
281
+ toJSON() {
282
+ return {
283
+ logClusterDepth: this.logClusterDepth,
284
+ maxNodeDepth: this.maxNodeDepth,
285
+ simTh: this.simTh,
286
+ maxChildren: this.maxChildren,
287
+ rootNode: this.rootNode.toJSON(),
288
+ maxClusters: this.maxClusters,
289
+ extraDelimiters: [...this.extraDelimiters],
290
+ paramStr: this.paramStr,
291
+ parametrizeNumericTokens: this.parametrizeNumericTokens,
292
+ clusters: this.getClusters().map((c) => c.toJSON()),
293
+ clustersCounter: this.clustersCounter,
294
+ };
295
+ }
296
+ static fromJSON(data) {
297
+ const drain = new Drain({
298
+ logClusterDepth: data.logClusterDepth,
299
+ simTh: data.simTh,
300
+ maxChildren: data.maxChildren,
301
+ maxClusters: data.maxClusters,
302
+ extraDelimiters: data.extraDelimiters,
303
+ paramStr: data.paramStr,
304
+ parametrizeNumericTokens: data.parametrizeNumericTokens,
305
+ });
306
+ drain.rootNode.keyToChildNode.clear();
307
+ drain.rootNode.clusterIds = [];
308
+ const rootNode = Node.fromJSON(data.rootNode);
309
+ for (const [key, node] of rootNode.keyToChildNode) {
310
+ drain.rootNode.keyToChildNode.set(key, node);
311
+ }
312
+ drain.rootNode.clusterIds = rootNode.clusterIds;
313
+ for (const clusterData of data.clusters) {
314
+ const cluster = LogCluster.fromJSON(clusterData);
315
+ drain.idToCluster.set(cluster.clusterId, cluster);
316
+ }
317
+ drain.clustersCounter = data.clustersCounter;
318
+ return drain;
319
+ }
355
320
  }
356
321
  //# sourceMappingURL=Drain.js.map