@crawlee/core 4.0.0-beta.99 → 4.0.0-rc.1
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/README.md +1 -1
- package/configuration.d.ts +16 -47
- package/configuration.js +13 -25
- package/debug.js +4 -4
- package/errors.d.ts +28 -38
- package/errors.js +33 -47
- package/events/event_manager.d.ts +2 -2
- package/events/event_manager.js +7 -6
- package/events/index.d.ts +1 -0
- package/events/local_event_manager.d.ts +1 -8
- package/events/local_event_manager.js +13 -13
- package/events/system_info.d.ts +38 -0
- package/index.d.ts +2 -8
- package/index.js +4 -8
- package/internal.d.ts +8 -0
- package/internal.js +9 -0
- package/log.d.ts +10 -11
- package/log.js +52 -20
- package/memory-storage/memory-storage.d.ts +15 -18
- package/memory-storage/memory-storage.js +80 -58
- package/memory-storage/resource-clients/dataset.d.ts +1 -6
- package/memory-storage/resource-clients/dataset.js +23 -31
- package/memory-storage/resource-clients/key-value-store.d.ts +1 -10
- package/memory-storage/resource-clients/key-value-store.js +43 -67
- package/memory-storage/resource-clients/request-queue.d.ts +1 -42
- package/memory-storage/resource-clients/request-queue.js +109 -117
- package/owned_or_injected.d.ts +1 -3
- package/owned_or_injected.js +17 -17
- package/package.json +17 -20
- package/proxy_configuration.d.ts +21 -26
- package/proxy_configuration.js +35 -25
- package/recoverable_state.d.ts +104 -47
- package/recoverable_state.js +199 -74
- package/request.d.ts +20 -107
- package/request.js +78 -244
- package/serialization.js +17 -16
- package/service_locator.d.ts +22 -10
- package/service_locator.js +59 -48
- package/storages/batched_adds.d.ts +37 -0
- package/storages/batched_adds.js +73 -0
- package/storages/dataset.d.ts +13 -8
- package/storages/dataset.js +149 -40
- package/storages/index.d.ts +4 -4
- package/storages/index.js +2 -4
- package/storages/key_value_store.d.ts +16 -35
- package/storages/key_value_store.js +223 -110
- package/storages/key_value_store_codec.js +6 -11
- package/storages/request_dedup_cache.d.ts +1 -4
- package/storages/request_dedup_cache.js +15 -15
- package/storages/request_list.d.ts +9 -104
- package/storages/request_list.js +236 -233
- package/storages/request_loader.d.ts +49 -18
- package/storages/request_loader.js +36 -1
- package/storages/request_manager.d.ts +86 -0
- package/storages/request_manager_tandem.d.ts +14 -38
- package/storages/request_manager_tandem.js +67 -64
- package/storages/request_queue.d.ts +23 -50
- package/storages/request_queue.js +371 -226
- package/storages/storage_instance_manager.d.ts +2 -4
- package/storages/storage_instance_manager.js +21 -21
- package/storages/storage_stats.d.ts +1 -1
- package/storages/storage_stats.js +4 -4
- package/storages/transaction.d.ts +270 -0
- package/storages/transaction.js +296 -0
- package/storages/utils.d.ts +6 -3
- package/storages/utils.js +11 -2
- package/system-info/runtime.js +7 -7
- package/url.d.ts +9 -0
- package/url.js +11 -0
- package/validators.d.ts +23 -25
- package/validators.js +14 -25
- package/autoscaling/autoscaled_pool.d.ts +0 -213
- package/autoscaling/autoscaled_pool.js +0 -378
- package/autoscaling/client_load_signal.d.ts +0 -59
- package/autoscaling/client_load_signal.js +0 -73
- package/autoscaling/concurrency_system.d.ts +0 -283
- package/autoscaling/concurrency_system.js +0 -350
- package/autoscaling/cpu_load_signal.d.ts +0 -44
- package/autoscaling/cpu_load_signal.js +0 -46
- package/autoscaling/event_loop_load_signal.d.ts +0 -54
- package/autoscaling/event_loop_load_signal.js +0 -60
- package/autoscaling/index.d.ts +0 -9
- package/autoscaling/index.js +0 -9
- package/autoscaling/load_signal.d.ts +0 -99
- package/autoscaling/load_signal.js +0 -103
- package/autoscaling/memory_load_signal.d.ts +0 -56
- package/autoscaling/memory_load_signal.js +0 -106
- package/autoscaling/snapshotter.d.ts +0 -87
- package/autoscaling/snapshotter.js +0 -67
- package/autoscaling/system_status.d.ts +0 -161
- package/autoscaling/system_status.js +0 -139
- package/autoscaling/weighted_avg.d.ts +0 -5
- package/autoscaling/weighted_avg.js +0 -14
- package/cookie_utils.d.ts +0 -44
- package/cookie_utils.js +0 -122
- package/crawlers/context_pipeline.d.ts +0 -70
- package/crawlers/context_pipeline.js +0 -122
- package/crawlers/crawler_commons.d.ts +0 -257
- package/crawlers/crawler_commons.js +0 -107
- package/crawlers/error_snapshotter.d.ts +0 -59
- package/crawlers/error_snapshotter.js +0 -117
- package/crawlers/error_tracker.d.ts +0 -54
- package/crawlers/error_tracker.js +0 -308
- package/crawlers/index.d.ts +0 -5
- package/crawlers/index.js +0 -5
- package/crawlers/internals/types.d.ts +0 -7
- package/crawlers/statistics.d.ts +0 -209
- package/crawlers/statistics.js +0 -350
- package/enqueue_links/enqueue_links.d.ts +0 -264
- package/enqueue_links/enqueue_links.js +0 -271
- package/enqueue_links/index.d.ts +0 -2
- package/enqueue_links/index.js +0 -2
- package/enqueue_links/shared.d.ts +0 -83
- package/enqueue_links/shared.js +0 -221
- package/router.d.ts +0 -309
- package/router.js +0 -309
- package/session_pool/consts.d.ts +0 -3
- package/session_pool/consts.js +0 -3
- package/session_pool/errors.d.ts +0 -7
- package/session_pool/errors.js +0 -11
- package/session_pool/fingerprint.d.ts +0 -9
- package/session_pool/fingerprint.js +0 -30
- package/session_pool/index.d.ts +0 -4
- package/session_pool/index.js +0 -4
- package/session_pool/session.d.ts +0 -161
- package/session_pool/session.js +0 -218
- package/session_pool/session_pool.d.ts +0 -246
- package/session_pool/session_pool.js +0 -386
- package/storages/access_checking.d.ts +0 -12
- package/storages/access_checking.js +0 -17
- package/storages/sitemap_request_loader.d.ts +0 -249
- package/storages/sitemap_request_loader.js +0 -432
- /package/{crawlers/internals/types.js → events/system_info.js} +0 -0
|
@@ -1,308 +0,0 @@
|
|
|
1
|
-
import { inspect } from 'node:util';
|
|
2
|
-
import { ErrorSnapshotter } from './error_snapshotter.js';
|
|
3
|
-
const extractPathFromStackTraceLine = (line) => {
|
|
4
|
-
const lastStartingRoundBracketIndex = line.lastIndexOf('(');
|
|
5
|
-
if (lastStartingRoundBracketIndex !== -1) {
|
|
6
|
-
const closingRoundBracketIndex = line.indexOf(')', lastStartingRoundBracketIndex);
|
|
7
|
-
if (closingRoundBracketIndex !== -1) {
|
|
8
|
-
return line.slice(lastStartingRoundBracketIndex + 1, closingRoundBracketIndex);
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
return line;
|
|
12
|
-
};
|
|
13
|
-
// https://v8.dev/docs/stack-trace-api#appendix%3A-stack-trace-format
|
|
14
|
-
const getPathFromStackTrace = (stack) => {
|
|
15
|
-
for (const line of stack) {
|
|
16
|
-
const path = extractPathFromStackTraceLine(line);
|
|
17
|
-
if (path.startsWith('node:') || path.includes('/node_modules/') || path.includes('\\node_modules\\')) {
|
|
18
|
-
continue;
|
|
19
|
-
}
|
|
20
|
-
return path;
|
|
21
|
-
}
|
|
22
|
-
return extractPathFromStackTraceLine(stack[0]);
|
|
23
|
-
};
|
|
24
|
-
const getStackTraceGroup = (error, storage, showFullStack) => {
|
|
25
|
-
const stack = error.stack?.split('\n').map((line) => line.trim());
|
|
26
|
-
let sliceAt = -1;
|
|
27
|
-
if (stack) {
|
|
28
|
-
for (let i = 0; i < stack.length; i++) {
|
|
29
|
-
if (stack[i].startsWith('at ') || stack[i].startsWith('eval at ')) {
|
|
30
|
-
sliceAt = i;
|
|
31
|
-
break;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
let normalizedStackTrace = null;
|
|
36
|
-
if (sliceAt !== -1) {
|
|
37
|
-
normalizedStackTrace = showFullStack
|
|
38
|
-
? stack
|
|
39
|
-
.slice(sliceAt)
|
|
40
|
-
.map((x) => x.trim())
|
|
41
|
-
.join('\n')
|
|
42
|
-
: getPathFromStackTrace(stack.slice(sliceAt));
|
|
43
|
-
}
|
|
44
|
-
if (!normalizedStackTrace) {
|
|
45
|
-
normalizedStackTrace = 'missing stack trace';
|
|
46
|
-
}
|
|
47
|
-
if (!(normalizedStackTrace in storage)) {
|
|
48
|
-
storage[normalizedStackTrace] = Object.create(null);
|
|
49
|
-
}
|
|
50
|
-
return storage[normalizedStackTrace];
|
|
51
|
-
};
|
|
52
|
-
const getErrorCodeGroup = (error, storage) => {
|
|
53
|
-
let { code } = error;
|
|
54
|
-
if (code === undefined) {
|
|
55
|
-
code = 'missing error code';
|
|
56
|
-
}
|
|
57
|
-
if (!(code in storage)) {
|
|
58
|
-
storage[code] = Object.create(null);
|
|
59
|
-
}
|
|
60
|
-
return storage[String(code)];
|
|
61
|
-
};
|
|
62
|
-
const getErrorNameGroup = (error, storage) => {
|
|
63
|
-
const { name } = error;
|
|
64
|
-
if (!(name in storage)) {
|
|
65
|
-
storage[name] = Object.create(null);
|
|
66
|
-
}
|
|
67
|
-
return storage[name];
|
|
68
|
-
};
|
|
69
|
-
const findBiggestWordIntersection = (a, b) => {
|
|
70
|
-
let maxStreak = 0;
|
|
71
|
-
let bStreakIndex = -1;
|
|
72
|
-
let aStreakIndex = -1;
|
|
73
|
-
for (let aIndex = 0; aIndex < a.length; aIndex++) {
|
|
74
|
-
let bIndex = -1;
|
|
75
|
-
do {
|
|
76
|
-
let aWalkIndex = aIndex;
|
|
77
|
-
bIndex = b.indexOf(a[aIndex], bIndex + 1);
|
|
78
|
-
let bWalkIndex = bIndex;
|
|
79
|
-
let streak = 0;
|
|
80
|
-
while (aWalkIndex < a.length && bWalkIndex < b.length && b[bWalkIndex++] === a[aWalkIndex++]) {
|
|
81
|
-
streak++;
|
|
82
|
-
}
|
|
83
|
-
if (streak > maxStreak) {
|
|
84
|
-
maxStreak = streak;
|
|
85
|
-
aStreakIndex = aIndex;
|
|
86
|
-
bStreakIndex = bIndex;
|
|
87
|
-
}
|
|
88
|
-
} while (bIndex !== -1);
|
|
89
|
-
}
|
|
90
|
-
return {
|
|
91
|
-
maxStreak,
|
|
92
|
-
aStreakIndex,
|
|
93
|
-
bStreakIndex,
|
|
94
|
-
};
|
|
95
|
-
};
|
|
96
|
-
const arrayCount = (array, target) => {
|
|
97
|
-
let result = 0;
|
|
98
|
-
for (const item of array) {
|
|
99
|
-
if (item === target) {
|
|
100
|
-
result++;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
return result;
|
|
104
|
-
};
|
|
105
|
-
const calculatePlaceholder = (a, b) => {
|
|
106
|
-
const { maxStreak, aStreakIndex, bStreakIndex } = findBiggestWordIntersection(a, b);
|
|
107
|
-
if (maxStreak === 0) {
|
|
108
|
-
return ['_'];
|
|
109
|
-
}
|
|
110
|
-
const leftA = a.slice(0, aStreakIndex);
|
|
111
|
-
const leftB = b.slice(0, bStreakIndex);
|
|
112
|
-
const rightA = a.slice(aStreakIndex + maxStreak);
|
|
113
|
-
const rightB = b.slice(bStreakIndex + maxStreak);
|
|
114
|
-
const output = [];
|
|
115
|
-
if (leftA.length !== 0 || leftB.length !== 0) {
|
|
116
|
-
output.push(...calculatePlaceholder(leftA, leftB));
|
|
117
|
-
}
|
|
118
|
-
output.push(...a.slice(aStreakIndex, aStreakIndex + maxStreak));
|
|
119
|
-
if (rightA.length !== 0 || rightB.length !== 0) {
|
|
120
|
-
output.push(...calculatePlaceholder(rightA, rightB));
|
|
121
|
-
}
|
|
122
|
-
return output;
|
|
123
|
-
};
|
|
124
|
-
const normalizedCalculatePlaceholder = (a, b) => {
|
|
125
|
-
const output = calculatePlaceholder(a, b);
|
|
126
|
-
// We can't be too general
|
|
127
|
-
if (arrayCount(output, '_') / output.length >= 0.5) {
|
|
128
|
-
return ['_'];
|
|
129
|
-
}
|
|
130
|
-
return output;
|
|
131
|
-
};
|
|
132
|
-
// Merge A (missing placeholders) into B (can contain placeholders but does not have to)
|
|
133
|
-
const mergeMessages = (a, b, storage) => {
|
|
134
|
-
const placeholder = normalizedCalculatePlaceholder(a.split(' '), b.split(' ')).join(' ');
|
|
135
|
-
if (placeholder === '_') {
|
|
136
|
-
return undefined;
|
|
137
|
-
}
|
|
138
|
-
const count = storage[a].count + storage[b].count;
|
|
139
|
-
delete storage[a];
|
|
140
|
-
delete storage[b];
|
|
141
|
-
storage[placeholder] = Object.assign(Object.create(null), {
|
|
142
|
-
count,
|
|
143
|
-
});
|
|
144
|
-
return placeholder;
|
|
145
|
-
};
|
|
146
|
-
const getErrorMessageGroup = (error, storage, showFullMessage) => {
|
|
147
|
-
let { message } = error;
|
|
148
|
-
if (!message) {
|
|
149
|
-
try {
|
|
150
|
-
message =
|
|
151
|
-
typeof error === 'string'
|
|
152
|
-
? error
|
|
153
|
-
: `Unknown error message. Received non-error object: ${JSON.stringify(error)}`;
|
|
154
|
-
}
|
|
155
|
-
catch {
|
|
156
|
-
message = `Unknown error message. Received non-error object, and could not stringify it: ${inspect(error, {
|
|
157
|
-
depth: 0,
|
|
158
|
-
})}`;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
if (!showFullMessage) {
|
|
162
|
-
const newLineIndex = message.indexOf('\n');
|
|
163
|
-
message = message.slice(0, newLineIndex === -1 ? undefined : newLineIndex);
|
|
164
|
-
}
|
|
165
|
-
if (!(message in storage)) {
|
|
166
|
-
storage[message] = Object.assign(Object.create(null), {
|
|
167
|
-
count: 0,
|
|
168
|
-
});
|
|
169
|
-
// This actually safe, since we Object.create(null) so no prototype pollution can happen.
|
|
170
|
-
// eslint-disable-next-line no-restricted-syntax, guard-for-in
|
|
171
|
-
for (const existingMessage in storage) {
|
|
172
|
-
const newMessage = mergeMessages(message, existingMessage, storage);
|
|
173
|
-
if (newMessage) {
|
|
174
|
-
message = newMessage;
|
|
175
|
-
break;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
return storage[message];
|
|
180
|
-
};
|
|
181
|
-
const increaseCount = (group) => {
|
|
182
|
-
if (!('count' in group)) {
|
|
183
|
-
// In case users don't want to display error message
|
|
184
|
-
group.count = 0;
|
|
185
|
-
}
|
|
186
|
-
group.count++;
|
|
187
|
-
};
|
|
188
|
-
/**
|
|
189
|
-
* This class tracks errors and computes a summary of information like:
|
|
190
|
-
* - where the errors happened
|
|
191
|
-
* - what the error names are
|
|
192
|
-
* - what the error codes are
|
|
193
|
-
* - what is the general error message
|
|
194
|
-
*
|
|
195
|
-
* This is extremely useful when there are dynamic error messages, such as argument validation.
|
|
196
|
-
*
|
|
197
|
-
* Since the structure of the `tracker.result` object differs when using different options,
|
|
198
|
-
* it's typed as `Record<string, unknown>`. The most deep object has a `count` property, which is a number.
|
|
199
|
-
*
|
|
200
|
-
* It's possible to get the total amount of errors via the `tracker.total` property.
|
|
201
|
-
*/
|
|
202
|
-
export class ErrorTracker {
|
|
203
|
-
#options;
|
|
204
|
-
result;
|
|
205
|
-
total;
|
|
206
|
-
errorSnapshotter;
|
|
207
|
-
constructor(options = {}) {
|
|
208
|
-
this.#options = {
|
|
209
|
-
showErrorCode: true,
|
|
210
|
-
showErrorName: true,
|
|
211
|
-
showStackTrace: true,
|
|
212
|
-
showFullStack: false,
|
|
213
|
-
showErrorMessage: true,
|
|
214
|
-
showFullMessage: false,
|
|
215
|
-
saveErrorSnapshots: false,
|
|
216
|
-
...options,
|
|
217
|
-
};
|
|
218
|
-
if (this.#options.saveErrorSnapshots) {
|
|
219
|
-
this.errorSnapshotter = new ErrorSnapshotter();
|
|
220
|
-
}
|
|
221
|
-
this.result = Object.create(null);
|
|
222
|
-
this.total = 0;
|
|
223
|
-
}
|
|
224
|
-
updateGroup(error) {
|
|
225
|
-
let group = this.result;
|
|
226
|
-
if (this.#options.showStackTrace) {
|
|
227
|
-
group = getStackTraceGroup(error, group, this.#options.showFullStack);
|
|
228
|
-
}
|
|
229
|
-
if (this.#options.showErrorCode) {
|
|
230
|
-
group = getErrorCodeGroup(error, group);
|
|
231
|
-
}
|
|
232
|
-
if (this.#options.showErrorName) {
|
|
233
|
-
group = getErrorNameGroup(error, group);
|
|
234
|
-
}
|
|
235
|
-
if (this.#options.showErrorMessage) {
|
|
236
|
-
group = getErrorMessageGroup(error, group, this.#options.showFullMessage);
|
|
237
|
-
}
|
|
238
|
-
increaseCount(group);
|
|
239
|
-
return group;
|
|
240
|
-
}
|
|
241
|
-
add(error) {
|
|
242
|
-
this.total++;
|
|
243
|
-
this.updateGroup(error);
|
|
244
|
-
if (typeof error.cause === 'object' && error.cause !== null) {
|
|
245
|
-
this.add(error.cause);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
/**
|
|
249
|
-
* This method is async, because it captures a snapshot of the error context.
|
|
250
|
-
* We added this new method to avoid breaking changes.
|
|
251
|
-
*/
|
|
252
|
-
async addAsync(error, context) {
|
|
253
|
-
this.total++;
|
|
254
|
-
const group = this.updateGroup(error);
|
|
255
|
-
// Capture a snapshot (screenshot and HTML) on the first occurrence of an error
|
|
256
|
-
if (group.count === 1 && context) {
|
|
257
|
-
await this.captureSnapshot(group, error, context).catch(() => { });
|
|
258
|
-
}
|
|
259
|
-
if (typeof error.cause === 'object' && error.cause !== null) {
|
|
260
|
-
await this.addAsync(error.cause);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
getUniqueErrorCount() {
|
|
264
|
-
let count = 0;
|
|
265
|
-
const goDeeper = (group) => {
|
|
266
|
-
if ('count' in group) {
|
|
267
|
-
count++;
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
// eslint-disable-next-line guard-for-in, no-restricted-syntax
|
|
271
|
-
for (const key in group) {
|
|
272
|
-
goDeeper(group[key]);
|
|
273
|
-
}
|
|
274
|
-
};
|
|
275
|
-
goDeeper(this.result);
|
|
276
|
-
return count;
|
|
277
|
-
}
|
|
278
|
-
getMostPopularErrors(count) {
|
|
279
|
-
const result = [];
|
|
280
|
-
const goDeeper = (group, path) => {
|
|
281
|
-
if ('count' in group) {
|
|
282
|
-
result.push([group.count, path]);
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
// eslint-disable-next-line guard-for-in, no-restricted-syntax
|
|
286
|
-
for (const key in group) {
|
|
287
|
-
goDeeper(group[key], [...path, key]);
|
|
288
|
-
}
|
|
289
|
-
};
|
|
290
|
-
goDeeper(this.result, []);
|
|
291
|
-
return result.sort((a, b) => b[0] - a[0]).slice(0, count);
|
|
292
|
-
}
|
|
293
|
-
async captureSnapshot(storage, error, context) {
|
|
294
|
-
if (!this.errorSnapshotter) {
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
297
|
-
const { screenshotFileUrl, htmlFileUrl } = await this.errorSnapshotter.captureSnapshot(error, context);
|
|
298
|
-
storage.firstErrorScreenshotUrl = screenshotFileUrl;
|
|
299
|
-
storage.firstErrorHtmlUrl = htmlFileUrl;
|
|
300
|
-
}
|
|
301
|
-
reset() {
|
|
302
|
-
// This actually safe, since we Object.create(null) so no prototype pollution can happen.
|
|
303
|
-
// eslint-disable-next-line no-restricted-syntax, guard-for-in
|
|
304
|
-
for (const key in this.result) {
|
|
305
|
-
delete this.result[key];
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
}
|
package/crawlers/index.d.ts
DELETED
package/crawlers/index.js
DELETED
package/crawlers/statistics.d.ts
DELETED
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
import type { CrawleeLogger } from '../log.js';
|
|
2
|
-
import { KeyValueStore } from '../storages/key_value_store.js';
|
|
3
|
-
import { ErrorTracker } from './error_tracker.js';
|
|
4
|
-
/**
|
|
5
|
-
* Persistence-related options to control how and when crawler's data gets persisted.
|
|
6
|
-
*/
|
|
7
|
-
export interface PersistenceOptions {
|
|
8
|
-
/**
|
|
9
|
-
* Use this flag to disable or enable periodic persistence to key value store.
|
|
10
|
-
* @default true
|
|
11
|
-
*/
|
|
12
|
-
enable?: boolean;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* The statistics class provides an interface to collecting and logging run
|
|
16
|
-
* statistics for requests.
|
|
17
|
-
*
|
|
18
|
-
* All statistic information is saved on key value store
|
|
19
|
-
* under the key `CRAWLEE_CRAWLER_STATISTICS_*`, persists between
|
|
20
|
-
* migrations and abort/resurrect
|
|
21
|
-
*
|
|
22
|
-
* @category Crawlers
|
|
23
|
-
*/
|
|
24
|
-
export declare class Statistics {
|
|
25
|
-
private static id;
|
|
26
|
-
/**
|
|
27
|
-
* An error tracker for final retry errors.
|
|
28
|
-
*/
|
|
29
|
-
readonly errorTracker: ErrorTracker;
|
|
30
|
-
/**
|
|
31
|
-
* An error tracker for retry errors prior to the final retry.
|
|
32
|
-
*/
|
|
33
|
-
readonly errorTrackerRetry: ErrorTracker;
|
|
34
|
-
/**
|
|
35
|
-
* Statistic instance id.
|
|
36
|
-
*/
|
|
37
|
-
readonly id: string;
|
|
38
|
-
/**
|
|
39
|
-
* Current statistic state used for doing calculations on {@link Statistics.calculate} calls
|
|
40
|
-
*/
|
|
41
|
-
state: StatisticState;
|
|
42
|
-
/**
|
|
43
|
-
* Contains the current retries histogram. Index 0 means 0 retries, index 2, 2 retries, and so on
|
|
44
|
-
*/
|
|
45
|
-
readonly requestRetryHistogram: number[];
|
|
46
|
-
protected keyValueStore?: KeyValueStore;
|
|
47
|
-
protected readonly persistStateKey: string;
|
|
48
|
-
private logIntervalMillis;
|
|
49
|
-
private logMessage;
|
|
50
|
-
private listener;
|
|
51
|
-
private requestsInProgress;
|
|
52
|
-
private readonly log;
|
|
53
|
-
private instanceStart;
|
|
54
|
-
private logInterval;
|
|
55
|
-
private _events?;
|
|
56
|
-
private persistenceOptions;
|
|
57
|
-
private get events();
|
|
58
|
-
/**
|
|
59
|
-
* @internal
|
|
60
|
-
*/
|
|
61
|
-
constructor(options?: StatisticsOptions);
|
|
62
|
-
/**
|
|
63
|
-
* Set the current statistic instance to pristine values
|
|
64
|
-
*/
|
|
65
|
-
reset(): void;
|
|
66
|
-
/**
|
|
67
|
-
* @param options - Override the persistence options provided in the constructor
|
|
68
|
-
*/
|
|
69
|
-
resetStore(options?: PersistenceOptions): Promise<void>;
|
|
70
|
-
/**
|
|
71
|
-
* Increments the status code counter.
|
|
72
|
-
*/
|
|
73
|
-
registerStatusCode(code: number): void;
|
|
74
|
-
/**
|
|
75
|
-
* Starts a job
|
|
76
|
-
* @ignore
|
|
77
|
-
*/
|
|
78
|
-
startJob(id: number | string): void;
|
|
79
|
-
/**
|
|
80
|
-
* Mark job as finished and sets the state
|
|
81
|
-
* @ignore
|
|
82
|
-
*/
|
|
83
|
-
finishJob(id: number | string, retryCount: number): void;
|
|
84
|
-
/**
|
|
85
|
-
* Mark job as failed and sets the state
|
|
86
|
-
* @ignore
|
|
87
|
-
*/
|
|
88
|
-
failJob(id: number | string, retryCount: number): void;
|
|
89
|
-
/**
|
|
90
|
-
* Discards a started job without affecting the finished/failed counters, e.g. when a request
|
|
91
|
-
* turns out to be skipped (robots.txt, enqueue strategy) after `startJob` was already called for it.
|
|
92
|
-
* @ignore
|
|
93
|
-
*/
|
|
94
|
-
discardJob(id: number | string): void;
|
|
95
|
-
/**
|
|
96
|
-
* Calculate the current statistics
|
|
97
|
-
*/
|
|
98
|
-
calculate(): {
|
|
99
|
-
requestAvgFailedDurationMillis: number;
|
|
100
|
-
requestAvgFinishedDurationMillis: number;
|
|
101
|
-
requestsFinishedPerMinute: number;
|
|
102
|
-
requestsFailedPerMinute: number;
|
|
103
|
-
requestTotalDurationMillis: number;
|
|
104
|
-
requestsTotal: number;
|
|
105
|
-
crawlerRuntimeMillis: number;
|
|
106
|
-
};
|
|
107
|
-
/**
|
|
108
|
-
* Initializes the key value store for persisting the statistics,
|
|
109
|
-
* displaying the current state in predefined intervals
|
|
110
|
-
*/
|
|
111
|
-
startCapturing(): Promise<void>;
|
|
112
|
-
/**
|
|
113
|
-
* Stops logging and remove event listeners, then persist
|
|
114
|
-
*/
|
|
115
|
-
stopCapturing(): Promise<void>;
|
|
116
|
-
private saveRetryCountForJob;
|
|
117
|
-
/**
|
|
118
|
-
* Persist internal state to the key value store
|
|
119
|
-
* @param options - Override the persistence options provided in the constructor
|
|
120
|
-
*/
|
|
121
|
-
persistState(options?: PersistenceOptions): Promise<void>;
|
|
122
|
-
/**
|
|
123
|
-
* Loads the current statistic from the key value store if any
|
|
124
|
-
*/
|
|
125
|
-
protected maybeLoadStatistics(): Promise<void>;
|
|
126
|
-
private teardown;
|
|
127
|
-
/**
|
|
128
|
-
* Make this class serializable when called with `JSON.stringify(statsInstance)` directly
|
|
129
|
-
* or through `keyValueStore.setValue('KEY', statsInstance)`
|
|
130
|
-
*/
|
|
131
|
-
toJSON(): StatisticPersistedState;
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Configuration for the {@link Statistics} instance used by the crawler
|
|
135
|
-
*/
|
|
136
|
-
export interface StatisticsOptions {
|
|
137
|
-
/**
|
|
138
|
-
* Interval in seconds to log the current statistics
|
|
139
|
-
* @default 60
|
|
140
|
-
*/
|
|
141
|
-
logIntervalSecs?: number;
|
|
142
|
-
/**
|
|
143
|
-
* Message to log with the current statistics
|
|
144
|
-
* @default 'Statistics'
|
|
145
|
-
*/
|
|
146
|
-
logMessage?: string;
|
|
147
|
-
/**
|
|
148
|
-
* Parent logger instance, the statistics will create a child logger from this.
|
|
149
|
-
* @default crawler.log
|
|
150
|
-
*/
|
|
151
|
-
log?: CrawleeLogger;
|
|
152
|
-
/**
|
|
153
|
-
* Key value store instance to persist the statistics.
|
|
154
|
-
* If not provided, the default one will be used when capturing starts
|
|
155
|
-
*/
|
|
156
|
-
keyValueStore?: KeyValueStore;
|
|
157
|
-
/**
|
|
158
|
-
* Control how and when to persist the statistics.
|
|
159
|
-
*/
|
|
160
|
-
persistenceOptions?: PersistenceOptions;
|
|
161
|
-
/**
|
|
162
|
-
* Save HTML snapshot (and a screenshot if possible) when an error occurs.
|
|
163
|
-
* @default false
|
|
164
|
-
*/
|
|
165
|
-
saveErrorSnapshots?: boolean;
|
|
166
|
-
/**
|
|
167
|
-
* A unique identifier for this statistics instance. This ID is used for persistence
|
|
168
|
-
* to the key value store, ensuring the same statistics can be loaded after script restarts.
|
|
169
|
-
*
|
|
170
|
-
* If not provided, an auto-incremented ID will be used for backward compatibility.
|
|
171
|
-
* This means statistics may not persist correctly across script restarts
|
|
172
|
-
* if crawler creation order changes.
|
|
173
|
-
*/
|
|
174
|
-
id?: string;
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Format of the persisted stats
|
|
178
|
-
*/
|
|
179
|
-
export interface StatisticPersistedState extends Omit<StatisticState, 'statsPersistedAt'> {
|
|
180
|
-
requestRetryHistogram: number[];
|
|
181
|
-
statsId: string;
|
|
182
|
-
requestAvgFailedDurationMillis: number;
|
|
183
|
-
requestAvgFinishedDurationMillis: number;
|
|
184
|
-
requestTotalDurationMillis: number;
|
|
185
|
-
requestsTotal: number;
|
|
186
|
-
crawlerLastStartTimestamp: number;
|
|
187
|
-
statsPersistedAt: string;
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Contains the statistics state
|
|
191
|
-
*/
|
|
192
|
-
export interface StatisticState {
|
|
193
|
-
requestsFinished: number;
|
|
194
|
-
requestsFailed: number;
|
|
195
|
-
requestsRetries: number;
|
|
196
|
-
requestsFailedPerMinute: number;
|
|
197
|
-
requestsFinishedPerMinute: number;
|
|
198
|
-
requestMinDurationMillis: number;
|
|
199
|
-
requestMaxDurationMillis: number;
|
|
200
|
-
requestTotalFailedDurationMillis: number;
|
|
201
|
-
requestTotalFinishedDurationMillis: number;
|
|
202
|
-
crawlerStartedAt: Date | string | null;
|
|
203
|
-
crawlerFinishedAt: Date | string | null;
|
|
204
|
-
crawlerRuntimeMillis: number;
|
|
205
|
-
statsPersistedAt: Date | string | null;
|
|
206
|
-
errors: Record<string, unknown>;
|
|
207
|
-
retryErrors: Record<string, unknown>;
|
|
208
|
-
requestsWithStatusCode: Record<string, number>;
|
|
209
|
-
}
|