@crawlee/core 4.0.0-beta.15 → 4.0.0-beta.150

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 (287) hide show
  1. package/README.md +14 -14
  2. package/autoscaling/autoscaled_pool.d.ts +73 -177
  3. package/autoscaling/autoscaled_pool.js +182 -329
  4. package/autoscaling/concurrency_system.d.ts +268 -0
  5. package/autoscaling/concurrency_system.js +364 -0
  6. package/autoscaling/cpu_load_signal.d.ts +43 -0
  7. package/autoscaling/cpu_load_signal.js +47 -0
  8. package/autoscaling/event_loop_load_signal.d.ts +51 -0
  9. package/autoscaling/event_loop_load_signal.js +60 -0
  10. package/autoscaling/index.d.ts +6 -1
  11. package/autoscaling/index.js +6 -1
  12. package/autoscaling/load_signal.d.ts +98 -0
  13. package/autoscaling/load_signal.js +103 -0
  14. package/autoscaling/memory_load_signal.d.ts +47 -0
  15. package/autoscaling/memory_load_signal.js +106 -0
  16. package/autoscaling/snapshotter.d.ts +58 -163
  17. package/autoscaling/snapshotter.js +45 -263
  18. package/autoscaling/storage_backend_load_signal.d.ts +56 -0
  19. package/autoscaling/storage_backend_load_signal.js +73 -0
  20. package/autoscaling/system_status.d.ts +67 -89
  21. package/autoscaling/system_status.js +92 -122
  22. package/autoscaling/weighted_avg.d.ts +5 -0
  23. package/autoscaling/weighted_avg.js +14 -0
  24. package/byte_utils.d.ts +17 -0
  25. package/byte_utils.js +42 -0
  26. package/configuration.d.ts +96 -223
  27. package/configuration.js +170 -222
  28. package/cookie_utils.d.ts +3 -2
  29. package/cookie_utils.js +18 -7
  30. package/crawlers/context_pipeline.d.ts +10 -1
  31. package/crawlers/context_pipeline.js +31 -8
  32. package/crawlers/crawler_commons.d.ts +90 -126
  33. package/crawlers/crawler_commons.js +1 -108
  34. package/crawlers/error_snapshotter.d.ts +2 -5
  35. package/crawlers/error_snapshotter.js +7 -8
  36. package/crawlers/error_tracker.d.ts +0 -1
  37. package/crawlers/error_tracker.js +0 -1
  38. package/crawlers/index.d.ts +1 -3
  39. package/crawlers/index.js +0 -3
  40. package/crawlers/internals/types.d.ts +0 -1
  41. package/crawlers/internals/types.js +0 -1
  42. package/crawlers/statistics.d.ts +187 -64
  43. package/crawlers/statistics.js +354 -165
  44. package/debug.d.ts +36 -0
  45. package/debug.js +70 -0
  46. package/enqueue_links/enqueue_links.d.ts +61 -154
  47. package/enqueue_links/enqueue_links.js +40 -232
  48. package/enqueue_links/index.d.ts +0 -1
  49. package/enqueue_links/index.js +0 -1
  50. package/enqueue_links/shared.d.ts +55 -28
  51. package/enqueue_links/shared.js +116 -69
  52. package/errors.d.ts +72 -4
  53. package/errors.js +89 -5
  54. package/events/event_manager.d.ts +35 -9
  55. package/events/event_manager.js +12 -13
  56. package/events/index.d.ts +0 -1
  57. package/events/index.js +0 -1
  58. package/events/local_event_manager.d.ts +15 -3
  59. package/events/local_event_manager.js +39 -13
  60. package/http.d.ts +9 -0
  61. package/http.js +28 -0
  62. package/index.d.ts +7 -5
  63. package/index.js +8 -4
  64. package/iterables.d.ts +79 -0
  65. package/iterables.js +134 -0
  66. package/log.d.ts +77 -1
  67. package/log.js +104 -1
  68. package/memory-storage/consts.d.ts +4 -0
  69. package/memory-storage/consts.js +4 -0
  70. package/memory-storage/index.d.ts +1 -0
  71. package/memory-storage/index.js +1 -0
  72. package/memory-storage/memory-storage.d.ts +44 -0
  73. package/memory-storage/memory-storage.js +160 -0
  74. package/memory-storage/resource-clients/common/base-client.d.ts +4 -0
  75. package/memory-storage/resource-clients/common/base-client.js +6 -0
  76. package/memory-storage/resource-clients/dataset.d.ts +40 -0
  77. package/memory-storage/resource-clients/dataset.js +106 -0
  78. package/memory-storage/resource-clients/key-value-store.d.ts +63 -0
  79. package/memory-storage/resource-clients/key-value-store.js +199 -0
  80. package/memory-storage/resource-clients/request-queue.d.ts +77 -0
  81. package/memory-storage/resource-clients/request-queue.js +407 -0
  82. package/memory-storage/utils.d.ts +16 -0
  83. package/memory-storage/utils.js +41 -0
  84. package/owned_or_injected.d.ts +58 -0
  85. package/owned_or_injected.js +98 -0
  86. package/package.json +13 -12
  87. package/proxy_configuration.d.ts +22 -128
  88. package/proxy_configuration.js +32 -144
  89. package/recoverable_state.d.ts +83 -51
  90. package/recoverable_state.js +163 -72
  91. package/request.d.ts +57 -16
  92. package/request.js +130 -69
  93. package/router.d.ts +193 -21
  94. package/router.js +188 -43
  95. package/serialization.d.ts +0 -1
  96. package/serialization.js +15 -15
  97. package/service_locator.d.ts +165 -0
  98. package/service_locator.js +253 -0
  99. package/session_pool/consts.d.ts +1 -2
  100. package/session_pool/consts.js +1 -2
  101. package/session_pool/errors.d.ts +0 -1
  102. package/session_pool/errors.js +0 -1
  103. package/session_pool/fingerprint.d.ts +9 -0
  104. package/session_pool/fingerprint.js +30 -0
  105. package/session_pool/index.d.ts +0 -2
  106. package/session_pool/index.js +0 -2
  107. package/session_pool/session.d.ts +39 -89
  108. package/session_pool/session.js +102 -159
  109. package/session_pool/session_pool.d.ts +67 -91
  110. package/session_pool/session_pool.js +196 -187
  111. package/storages/batched_adds.d.ts +37 -0
  112. package/storages/batched_adds.js +73 -0
  113. package/storages/dataset.d.ts +109 -56
  114. package/storages/dataset.js +284 -149
  115. package/storages/index.d.ts +9 -9
  116. package/storages/index.js +7 -9
  117. package/storages/key_value_store.d.ts +183 -48
  118. package/storages/key_value_store.js +444 -171
  119. package/storages/key_value_store_codec.d.ts +32 -0
  120. package/storages/key_value_store_codec.js +113 -0
  121. package/storages/request_dedup_cache.d.ts +22 -0
  122. package/storages/request_dedup_cache.js +48 -0
  123. package/storages/request_list.d.ts +53 -115
  124. package/storages/request_list.js +194 -167
  125. package/storages/request_loader.d.ts +133 -0
  126. package/storages/request_loader.js +36 -0
  127. package/storages/request_manager.d.ts +109 -0
  128. package/storages/request_manager.js +1 -0
  129. package/storages/request_manager_tandem.d.ts +55 -23
  130. package/storages/request_manager_tandem.js +139 -57
  131. package/storages/request_queue.d.ts +286 -48
  132. package/storages/request_queue.js +757 -218
  133. package/storages/{sitemap_request_list.d.ts → sitemap_request_loader.d.ts} +43 -91
  134. package/storages/sitemap_request_loader.js +439 -0
  135. package/storages/storage_instance_manager.d.ts +87 -0
  136. package/storages/storage_instance_manager.js +256 -0
  137. package/storages/storage_stats.d.ts +48 -0
  138. package/storages/storage_stats.js +29 -0
  139. package/storages/throttling_request_manager.d.ts +222 -0
  140. package/storages/throttling_request_manager.js +780 -0
  141. package/storages/transaction.d.ts +252 -0
  142. package/storages/transaction.js +251 -0
  143. package/storages/utils.d.ts +59 -11
  144. package/storages/utils.js +75 -15
  145. package/system-info/cpu-info.d.ts +67 -0
  146. package/system-info/cpu-info.js +216 -0
  147. package/system-info/memory-info.d.ts +31 -0
  148. package/system-info/memory-info.js +115 -0
  149. package/system-info/ps-tree.d.ts +17 -0
  150. package/system-info/ps-tree.js +144 -0
  151. package/system-info/runtime.d.ts +14 -0
  152. package/system-info/runtime.js +80 -0
  153. package/typedefs.d.ts +0 -6
  154. package/typedefs.js +0 -1
  155. package/url.d.ts +9 -0
  156. package/url.js +11 -0
  157. package/validators.d.ts +22 -18
  158. package/validators.js +13 -18
  159. package/autoscaling/autoscaled_pool.d.ts.map +0 -1
  160. package/autoscaling/autoscaled_pool.js.map +0 -1
  161. package/autoscaling/index.d.ts.map +0 -1
  162. package/autoscaling/index.js.map +0 -1
  163. package/autoscaling/snapshotter.d.ts.map +0 -1
  164. package/autoscaling/snapshotter.js.map +0 -1
  165. package/autoscaling/system_status.d.ts.map +0 -1
  166. package/autoscaling/system_status.js.map +0 -1
  167. package/configuration.d.ts.map +0 -1
  168. package/configuration.js.map +0 -1
  169. package/cookie_utils.d.ts.map +0 -1
  170. package/cookie_utils.js.map +0 -1
  171. package/crawlers/context_pipeline.d.ts.map +0 -1
  172. package/crawlers/context_pipeline.js.map +0 -1
  173. package/crawlers/crawler_commons.d.ts.map +0 -1
  174. package/crawlers/crawler_commons.js.map +0 -1
  175. package/crawlers/crawler_utils.d.ts +0 -10
  176. package/crawlers/crawler_utils.d.ts.map +0 -1
  177. package/crawlers/crawler_utils.js +0 -12
  178. package/crawlers/crawler_utils.js.map +0 -1
  179. package/crawlers/error_snapshotter.d.ts.map +0 -1
  180. package/crawlers/error_snapshotter.js.map +0 -1
  181. package/crawlers/error_tracker.d.ts.map +0 -1
  182. package/crawlers/error_tracker.js.map +0 -1
  183. package/crawlers/index.d.ts.map +0 -1
  184. package/crawlers/index.js.map +0 -1
  185. package/crawlers/internals/types.d.ts.map +0 -1
  186. package/crawlers/internals/types.js.map +0 -1
  187. package/crawlers/statistics.d.ts.map +0 -1
  188. package/crawlers/statistics.js.map +0 -1
  189. package/enqueue_links/enqueue_links.d.ts.map +0 -1
  190. package/enqueue_links/enqueue_links.js.map +0 -1
  191. package/enqueue_links/index.d.ts.map +0 -1
  192. package/enqueue_links/index.js.map +0 -1
  193. package/enqueue_links/shared.d.ts.map +0 -1
  194. package/enqueue_links/shared.js.map +0 -1
  195. package/errors.d.ts.map +0 -1
  196. package/errors.js.map +0 -1
  197. package/events/event_manager.d.ts.map +0 -1
  198. package/events/event_manager.js.map +0 -1
  199. package/events/index.d.ts.map +0 -1
  200. package/events/index.js.map +0 -1
  201. package/events/local_event_manager.d.ts.map +0 -1
  202. package/events/local_event_manager.js.map +0 -1
  203. package/http_clients/base-http-client.d.ts +0 -140
  204. package/http_clients/base-http-client.d.ts.map +0 -1
  205. package/http_clients/base-http-client.js +0 -40
  206. package/http_clients/base-http-client.js.map +0 -1
  207. package/http_clients/form-data-like.d.ts +0 -67
  208. package/http_clients/form-data-like.d.ts.map +0 -1
  209. package/http_clients/form-data-like.js +0 -5
  210. package/http_clients/form-data-like.js.map +0 -1
  211. package/http_clients/got-scraping-http-client.d.ts +0 -20
  212. package/http_clients/got-scraping-http-client.d.ts.map +0 -1
  213. package/http_clients/got-scraping-http-client.js +0 -85
  214. package/http_clients/got-scraping-http-client.js.map +0 -1
  215. package/http_clients/index.d.ts +0 -3
  216. package/http_clients/index.d.ts.map +0 -1
  217. package/http_clients/index.js +0 -3
  218. package/http_clients/index.js.map +0 -1
  219. package/index.d.ts.map +0 -1
  220. package/index.js.map +0 -1
  221. package/log.d.ts.map +0 -1
  222. package/log.js.map +0 -1
  223. package/proxy_configuration.d.ts.map +0 -1
  224. package/proxy_configuration.js.map +0 -1
  225. package/recoverable_state.d.ts.map +0 -1
  226. package/recoverable_state.js.map +0 -1
  227. package/request.d.ts.map +0 -1
  228. package/request.js.map +0 -1
  229. package/router.d.ts.map +0 -1
  230. package/router.js.map +0 -1
  231. package/serialization.d.ts.map +0 -1
  232. package/serialization.js.map +0 -1
  233. package/session_pool/consts.d.ts.map +0 -1
  234. package/session_pool/consts.js.map +0 -1
  235. package/session_pool/errors.d.ts.map +0 -1
  236. package/session_pool/errors.js.map +0 -1
  237. package/session_pool/events.d.ts +0 -3
  238. package/session_pool/events.d.ts.map +0 -1
  239. package/session_pool/events.js +0 -3
  240. package/session_pool/events.js.map +0 -1
  241. package/session_pool/index.d.ts.map +0 -1
  242. package/session_pool/index.js.map +0 -1
  243. package/session_pool/session.d.ts.map +0 -1
  244. package/session_pool/session.js.map +0 -1
  245. package/session_pool/session_pool.d.ts.map +0 -1
  246. package/session_pool/session_pool.js.map +0 -1
  247. package/storages/access_checking.d.ts +0 -13
  248. package/storages/access_checking.d.ts.map +0 -1
  249. package/storages/access_checking.js +0 -14
  250. package/storages/access_checking.js.map +0 -1
  251. package/storages/dataset.d.ts.map +0 -1
  252. package/storages/dataset.js.map +0 -1
  253. package/storages/index.d.ts.map +0 -1
  254. package/storages/index.js.map +0 -1
  255. package/storages/key_value_store.d.ts.map +0 -1
  256. package/storages/key_value_store.js.map +0 -1
  257. package/storages/request_list.d.ts.map +0 -1
  258. package/storages/request_list.js.map +0 -1
  259. package/storages/request_list_adapter.d.ts +0 -58
  260. package/storages/request_list_adapter.d.ts.map +0 -1
  261. package/storages/request_list_adapter.js +0 -81
  262. package/storages/request_list_adapter.js.map +0 -1
  263. package/storages/request_manager_tandem.d.ts.map +0 -1
  264. package/storages/request_manager_tandem.js.map +0 -1
  265. package/storages/request_provider.d.ts +0 -371
  266. package/storages/request_provider.d.ts.map +0 -1
  267. package/storages/request_provider.js +0 -585
  268. package/storages/request_provider.js.map +0 -1
  269. package/storages/request_queue.d.ts.map +0 -1
  270. package/storages/request_queue.js.map +0 -1
  271. package/storages/request_queue_v2.d.ts +0 -87
  272. package/storages/request_queue_v2.d.ts.map +0 -1
  273. package/storages/request_queue_v2.js +0 -438
  274. package/storages/request_queue_v2.js.map +0 -1
  275. package/storages/sitemap_request_list.d.ts.map +0 -1
  276. package/storages/sitemap_request_list.js +0 -430
  277. package/storages/sitemap_request_list.js.map +0 -1
  278. package/storages/storage_manager.d.ts +0 -58
  279. package/storages/storage_manager.d.ts.map +0 -1
  280. package/storages/storage_manager.js +0 -105
  281. package/storages/storage_manager.js.map +0 -1
  282. package/storages/utils.d.ts.map +0 -1
  283. package/storages/utils.js.map +0 -1
  284. package/typedefs.d.ts.map +0 -1
  285. package/typedefs.js.map +0 -1
  286. package/validators.d.ts.map +0 -1
  287. package/validators.js.map +0 -1
@@ -1,5 +1,5 @@
1
- import type { Log } from '@apify/log';
2
- import { Configuration } from '../configuration.js';
1
+ import type { CrawleeLogger } from '../log.js';
2
+ import type { SyncStateConversion } from '../recoverable_state.js';
3
3
  import { KeyValueStore } from '../storages/key_value_store.js';
4
4
  import { ErrorTracker } from './error_tracker.js';
5
5
  /**
@@ -12,65 +12,121 @@ export interface PersistenceOptions {
12
12
  */
13
13
  enable?: boolean;
14
14
  }
15
+ /**
16
+ * The statistics surface a crawler depends on: recording per-request outcomes, tracking errors, and driving the
17
+ * capture lifecycle for a run. Injected via the crawler's `statistics` option, so a custom implementation can be
18
+ * plugged in without subclassing the crawler.
19
+ *
20
+ * `StateExtension` describes the custom fields tracked alongside the built-in {@link StatisticState} ones - see
21
+ * {@link StatisticsOptions.stateExtension}.
22
+ *
23
+ * The owned-only mutators the crawler uses to *own* a default it built - `reset()`/`resetStore()` - are deliberately
24
+ * absent: an injected instance is borrowed, and the crawler never wipes it. Those live on the concrete
25
+ * {@link Statistics} only.
26
+ *
27
+ * @category Crawlers
28
+ */
29
+ export interface IStatistics<StateExtension extends object = {}> {
30
+ /** Tracker for errors on the final retry of a request. */
31
+ readonly errorTracker: ErrorTracker;
32
+ /** Tracker for errors on retries prior to the final one. */
33
+ readonly errorTrackerRetry: ErrorTracker;
34
+ /** The live statistics state the crawler reads for status messages and the final summary. */
35
+ readonly state: StatisticState & StateExtension;
36
+ /** Retries histogram - index `i` holds the number of requests that finished after `i` retries. */
37
+ readonly requestRetryHistogram: number[];
38
+ /** Marks a request as started, so its duration can be measured on finish/fail. */
39
+ startJob(id: number | string): void;
40
+ /** Marks a started request as finished, updating the finished counters and durations. */
41
+ finishJob(id: number | string, retryCount: number): void;
42
+ /** Marks a started request as failed, updating the failed counters and durations. */
43
+ failJob(id: number | string, retryCount: number): void;
44
+ /** Drops a started request without counting it as finished or failed (e.g. skipped by robots.txt). */
45
+ discardJob(id: number | string): void;
46
+ /** Increments the counter for the given HTTP status code. */
47
+ registerStatusCode(code: number): void;
48
+ /** Computes the derived aggregates (averages, per-minute rates, totals) from the current state. */
49
+ calculate(): CalculatedStatistics;
50
+ /** Begins a capture window: loads any persisted state, subscribes to persistence events, starts periodic logging. */
51
+ startCapturing(): Promise<void>;
52
+ /** Ends the capture window: stops logging, unsubscribes, and persists the final state. */
53
+ stopCapturing(): Promise<void>;
54
+ /**
55
+ * Persists the current state to the key-value store. Optional - the crawler calls it on migration, but a backend
56
+ * with no persistence of its own can omit it.
57
+ */
58
+ persistState?(): Promise<void>;
59
+ }
60
+ /** The derived aggregates computed by {@link IStatistics.calculate} from the current {@link StatisticState}. */
61
+ export interface CalculatedStatistics {
62
+ /** Mean duration of a failed request, in milliseconds; `Infinity` when nothing has failed. */
63
+ requestAvgFailedDurationMillis: number;
64
+ /** Mean duration of a finished request, in milliseconds; `Infinity` when nothing has finished. */
65
+ requestAvgFinishedDurationMillis: number;
66
+ /** Requests finished per minute over the run so far. */
67
+ requestsFinishedPerMinute: number;
68
+ /** Requests failed per minute over the run so far. */
69
+ requestsFailedPerMinute: number;
70
+ /** Combined duration of all finished and failed requests, in milliseconds. */
71
+ requestTotalDurationMillis: number;
72
+ /** Total number of settled requests (finished plus failed). */
73
+ requestsTotal: number;
74
+ /** Wall-clock runtime since capturing started, in milliseconds. */
75
+ crawlerRuntimeMillis: number;
76
+ }
15
77
  /**
16
78
  * The statistics class provides an interface to collecting and logging run
17
79
  * statistics for requests.
18
80
  *
19
81
  * All statistic information is saved on key value store
20
- * under the key `SDK_CRAWLER_STATISTICS_*`, persists between
82
+ * under the key `CRAWLEE_CRAWLER_STATISTICS_*`, persists between
21
83
  * migrations and abort/resurrect
22
84
  *
85
+ * Custom fields are tracked by passing {@link StatisticsOptions.stateExtension|`stateExtension`} - the extra fields are then part
86
+ * of {@link Statistics.state|`state`}, persisted and restored along with the built-in ones.
87
+ *
23
88
  * @category Crawlers
24
89
  */
25
- export declare class Statistics {
26
- private static id;
90
+ export declare class Statistics<StateExtension extends object = {}, PersistedStateExtension extends object = StateExtension> implements IStatistics<StateExtension> {
91
+ #private;
27
92
  /**
28
93
  * An error tracker for final retry errors.
29
94
  */
30
- errorTracker: ErrorTracker;
95
+ readonly errorTracker: ErrorTracker;
31
96
  /**
32
97
  * An error tracker for retry errors prior to the final retry.
33
98
  */
34
- errorTrackerRetry: ErrorTracker;
99
+ readonly errorTrackerRetry: ErrorTracker;
35
100
  /**
36
101
  * Statistic instance id.
37
102
  */
38
- readonly id: number;
103
+ readonly id: string;
104
+ private readonly log;
39
105
  /**
40
106
  * Current statistic state used for doing calculations on {@link Statistics.calculate} calls
41
107
  */
42
- state: StatisticState;
108
+ get state(): StatisticState & StateExtension;
43
109
  /**
44
110
  * Contains the current retries histogram. Index 0 means 0 retries, index 2, 2 retries, and so on
45
111
  */
46
- readonly requestRetryHistogram: number[];
47
- /**
48
- * Contains the associated Configuration instance
49
- */
50
- private readonly config;
51
- protected keyValueStore?: KeyValueStore;
52
- protected persistStateKey: string;
53
- private logIntervalMillis;
54
- private logMessage;
55
- private listener;
56
- private requestsInProgress;
57
- private readonly log;
58
- private instanceStart;
59
- private logInterval;
60
- private events;
61
- private persistenceOptions;
112
+ get requestRetryHistogram(): number[];
62
113
  /**
63
- * @internal
114
+ * Construct a statistics instance to pass to a crawler via its `statistics` option, e.g. to preconfigure
115
+ * persistence or error snapshots, share it across sequential runs, or track extra fields via `state`.
64
116
  */
65
- constructor(options?: StatisticsOptions);
117
+ constructor(options?: StatisticsOptions<StateExtension, PersistedStateExtension>);
66
118
  /**
67
- * Set the current statistic instance to pristine values
119
+ * Set the current statistic instance to pristine values.
120
+ *
121
+ * The persisted record is left alone - use {@link Statistics.resetStore} to clear that as well.
68
122
  */
69
123
  reset(): void;
70
124
  /**
71
- * @param options - Override the persistence options provided in the constructor
125
+ * Clear the persisted statistics record, leaving the in-memory state alone.
126
+ *
127
+ * Throws while capturing - the next PERSIST_STATE event would write the record straight back.
72
128
  */
73
- resetStore(options?: PersistenceOptions): Promise<void>;
129
+ resetStore(): Promise<void>;
74
130
  /**
75
131
  * Increments the status code counter.
76
132
  */
@@ -90,18 +146,16 @@ export declare class Statistics {
90
146
  * @ignore
91
147
  */
92
148
  failJob(id: number | string, retryCount: number): void;
149
+ /**
150
+ * Discards a started job without affecting the finished/failed counters, e.g. when a request
151
+ * turns out to be skipped (robots.txt, enqueue strategy) after `startJob` was already called for it.
152
+ * @ignore
153
+ */
154
+ discardJob(id: number | string): void;
93
155
  /**
94
156
  * Calculate the current statistics
95
157
  */
96
- calculate(): {
97
- requestAvgFailedDurationMillis: number;
98
- requestAvgFinishedDurationMillis: number;
99
- requestsFinishedPerMinute: number;
100
- requestsFailedPerMinute: number;
101
- requestTotalDurationMillis: number;
102
- requestsTotal: number;
103
- crawlerRuntimeMillis: number;
104
- };
158
+ calculate(): CalculatedStatistics;
105
159
  /**
106
160
  * Initializes the key value store for persisting the statistics,
107
161
  * displaying the current state in predefined intervals
@@ -111,27 +165,24 @@ export declare class Statistics {
111
165
  * Stops logging and remove event listeners, then persist
112
166
  */
113
167
  stopCapturing(): Promise<void>;
114
- protected _saveRetryCountForJob(retryCount: number): void;
115
- /**
116
- * Persist internal state to the key value store
117
- * @param options - Override the persistence options provided in the constructor
118
- */
119
- persistState(options?: PersistenceOptions): Promise<void>;
168
+ private saveRetryCountForJob;
120
169
  /**
121
- * Loads the current statistic from the key value store if any
170
+ * Persist internal state to the key value store.
171
+ *
172
+ * Statistics are bookkeeping - a store that refuses the write is worth a warning, not a failed crawl. The
173
+ * crawler calls this from its migration handler, where a rejection would go unhandled.
122
174
  */
123
- protected _maybeLoadStatistics(): Promise<void>;
124
- protected _teardown(): void;
175
+ persistState(): Promise<void>;
125
176
  /**
126
177
  * Make this class serializable when called with `JSON.stringify(statsInstance)` directly
127
178
  * or through `keyValueStore.setValue('KEY', statsInstance)`
128
179
  */
129
- toJSON(): StatisticPersistedState;
180
+ toJSON(): StatisticPersistedState & PersistedStateExtension;
130
181
  }
131
182
  /**
132
183
  * Configuration for the {@link Statistics} instance used by the crawler
133
184
  */
134
- export interface StatisticsOptions {
185
+ export interface StatisticsOptions<StateExtension extends object = {}, PersistedStateExtension extends object = StateExtension> {
135
186
  /**
136
187
  * Interval in seconds to log the current statistics
137
188
  * @default 60
@@ -146,17 +197,12 @@ export interface StatisticsOptions {
146
197
  * Parent logger instance, the statistics will create a child logger from this.
147
198
  * @default crawler.log
148
199
  */
149
- log?: Log;
200
+ log?: CrawleeLogger;
150
201
  /**
151
202
  * Key value store instance to persist the statistics.
152
203
  * If not provided, the default one will be used when capturing starts
153
204
  */
154
205
  keyValueStore?: KeyValueStore;
155
- /**
156
- * Configuration instance to use
157
- * @default Configuration.getGlobalConfig()
158
- */
159
- config?: Configuration;
160
206
  /**
161
207
  * Control how and when to persist the statistics.
162
208
  */
@@ -166,19 +212,90 @@ export interface StatisticsOptions {
166
212
  * @default false
167
213
  */
168
214
  saveErrorSnapshots?: boolean;
215
+ /**
216
+ * A unique identifier for this statistics instance. This ID is used for persistence
217
+ * to the key value store, ensuring the same statistics can be loaded after script restarts.
218
+ *
219
+ * If not provided, an auto-incremented ID will be used for backward compatibility.
220
+ * This means statistics may not persist correctly across script restarts
221
+ * if crawler creation order changes.
222
+ */
223
+ id?: string;
224
+ /**
225
+ * Custom fields to track alongside the built-in {@link StatisticState} ones. They become part of
226
+ * {@link Statistics.state|`state`} (typed as such), are persisted with the rest of the state, and are
227
+ * restored on migration or resurrect.
228
+ *
229
+ * ```ts
230
+ * const statistics = new Statistics({ stateExtension: { defaultState: { productsFound: 0 } } });
231
+ * statistics.state.productsFound++;
232
+ * ```
233
+ */
234
+ stateExtension?: StatisticStateExtensionOptions<StateExtension, PersistedStateExtension>;
169
235
  }
170
236
  /**
171
- * Format of the persisted stats
237
+ * How the custom fields of {@link StatisticsOptions.stateExtension} are initialized and converted to and from the
238
+ * persisted record - the same three things {@link RecoverableStateOptions} asks for, scoped to the custom half
239
+ * of the statistics state.
172
240
  */
173
- export interface StatisticPersistedState extends Omit<StatisticState, 'statsPersistedAt'> {
174
- requestRetryHistogram: number[];
175
- statsId: number;
176
- requestAvgFailedDurationMillis: number;
177
- requestAvgFinishedDurationMillis: number;
241
+ export interface StatisticStateExtensionOptions<StateExtension extends object, PersistedStateExtension extends object = StateExtension> {
242
+ /**
243
+ * The values the fields start with, and the ones {@link Statistics.reset} restores. A plain value is
244
+ * deep-copied with `structuredClone` each time it is used; pass a factory for a state `structuredClone` cannot
245
+ * rebuild.
246
+ *
247
+ * Can be omitted when `deserialize` supplies its own defaults, which is then the single place the fields are
248
+ * declared - see the example on {@link StatisticStateExtensionOptions.deserialize|`deserialize`}.
249
+ */
250
+ defaultState?: StateExtension | (() => StateExtension);
251
+ /**
252
+ * Rebuilds the custom fields from the persisted record, and the place to validate them before trusting them.
253
+ * Receives the whole record, so it has to supply a value for every field - `.default()` in a schema, or
254
+ * {@link StatisticStateExtensionOptions.defaultState|`defaultState`} alongside a conversion that copes with
255
+ * a missing field itself.
256
+ *
257
+ * ```ts
258
+ * const statistics = new Statistics({
259
+ * stateExtension: { deserialize: z.object({ productsFound: z.number().default(0) }) },
260
+ * });
261
+ * ```
262
+ *
263
+ * Without it, the declared fields are restored as they were persisted - which is a record off the key-value
264
+ * store taken at its word, `productsFound` included in whatever type it happens to hold.
265
+ *
266
+ * A conversion that rejects the record costs the custom fields their persisted values (they start from the
267
+ * defaults, with a warning) and nothing else.
268
+ */
269
+ deserialize?: SyncStateConversion<unknown, StateExtension>;
270
+ /**
271
+ * Converts the custom fields to the JSON-serializable form they are persisted in. Not needed for fields that
272
+ * already are one - pair it with `deserialize` for the fields that are not.
273
+ */
274
+ serialize?: SyncStateConversion<StateExtension, PersistedStateExtension>;
275
+ }
276
+ /**
277
+ * Format of the persisted stats.
278
+ *
279
+ * The `null`s are `Infinity` on the way out - JSON has no infinity, so a record written before anything
280
+ * finished or failed carries a `null` in its place.
281
+ */
282
+ export interface StatisticPersistedState extends Omit<StatisticState, 'statsPersistedAt' | 'crawlerStartedAt' | 'crawlerFinishedAt' | 'requestMinDurationMillis' | 'requestsFailedPerMinute' | 'requestsFinishedPerMinute' | 'requestRetryHistogram' | 'instanceStart'> {
283
+ statsId: string;
284
+ requestsFailedPerMinute: number | null;
285
+ requestsFinishedPerMinute: number | null;
286
+ /** ISO strings - the live state keeps these as `Date`s. */
287
+ crawlerStartedAt: string | null;
288
+ crawlerFinishedAt: string | null;
289
+ statsPersistedAt: string;
290
+ requestMinDurationMillis: number | null;
291
+ /** A retry count that no request ever reached leaves a `null` here. */
292
+ requestRetryHistogram: (number | null)[];
293
+ requestAvgFailedDurationMillis: number | null;
294
+ requestAvgFinishedDurationMillis: number | null;
178
295
  requestTotalDurationMillis: number;
179
296
  requestsTotal: number;
297
+ /** {@link StatisticState.instanceStart} of the run that wrote the record. */
180
298
  crawlerLastStartTimestamp: number;
181
- statsPersistedAt: string;
182
299
  }
183
300
  /**
184
301
  * Contains the statistics state
@@ -200,5 +317,11 @@ export interface StatisticState {
200
317
  errors: Record<string, unknown>;
201
318
  retryErrors: Record<string, unknown>;
202
319
  requestsWithStatusCode: Record<string, number>;
320
+ /** Retries histogram - index `i` holds the number of requests that finished after `i` retries. */
321
+ requestRetryHistogram: number[];
322
+ /**
323
+ * When the current capture window started, as a `Date.now()` timestamp. Rebased on load so that the runtime
324
+ * reported by {@link Statistics.calculate} spans a migration rather than restarting from zero.
325
+ */
326
+ instanceStart: number;
203
327
  }
204
- //# sourceMappingURL=statistics.d.ts.map