envio 3.3.0 → 3.3.1-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/package.json +6 -7
  2. package/src/ChainFetching.res +4 -32
  3. package/src/ChainFetching.res.mjs +2 -12
  4. package/src/ChainState.res +73 -53
  5. package/src/ChainState.res.mjs +61 -30
  6. package/src/ChainState.resi +13 -17
  7. package/src/Config.res +5 -0
  8. package/src/Config.res.mjs +1 -0
  9. package/src/CrossChainState.res +2 -8
  10. package/src/CrossChainState.res.mjs +6 -8
  11. package/src/CrossChainState.resi +1 -0
  12. package/src/EffectState.res +183 -44
  13. package/src/EffectState.res.mjs +134 -26
  14. package/src/EffectState.resi +26 -3
  15. package/src/EventProcessing.res +14 -9
  16. package/src/EventProcessing.res.mjs +7 -7
  17. package/src/FetchState.res +18 -29
  18. package/src/FetchState.res.mjs +20 -37
  19. package/src/IndexerState.res +280 -31
  20. package/src/IndexerState.res.mjs +234 -25
  21. package/src/IndexerState.resi +22 -0
  22. package/src/LoadLayer.res +19 -65
  23. package/src/LoadLayer.res.mjs +13 -55
  24. package/src/Main.res +42 -23
  25. package/src/Main.res.mjs +32 -35
  26. package/src/Metrics.res +943 -66
  27. package/src/Metrics.res.mjs +367 -50
  28. package/src/Persistence.res +3 -0
  29. package/src/PgStorage.res +3 -8
  30. package/src/PgStorage.res.mjs +3 -4
  31. package/src/PruneStaleHistory.res +1 -1
  32. package/src/PruneStaleHistory.res.mjs +1 -2
  33. package/src/Rollback.res +4 -5
  34. package/src/Rollback.res.mjs +2 -3
  35. package/src/SimulateItems.res.mjs +3 -21
  36. package/src/TestIndexer.res.mjs +4 -23
  37. package/src/TestIndexerProxyStorage.res +1 -0
  38. package/src/TestIndexerProxyStorage.res.mjs +1 -1
  39. package/src/Writing.res +3 -5
  40. package/src/Writing.res.mjs +3 -6
  41. package/src/bindings/ClickHouse.res +101 -17
  42. package/src/bindings/ClickHouse.res.mjs +58 -19
  43. package/src/bindings/NodeJs.res +64 -0
  44. package/src/bindings/NodeJs.res.mjs +6 -0
  45. package/src/sources/HyperSyncClient.res +5 -11
  46. package/src/sources/SourceManager.res +72 -27
  47. package/src/sources/SourceManager.res.mjs +81 -11
  48. package/src/sources/SourceManager.resi +14 -0
  49. package/src/tui/Tui.res +1 -1
  50. package/src/tui/Tui.res.mjs +2 -2
  51. package/src/Prometheus.res +0 -789
  52. package/src/Prometheus.res.mjs +0 -847
  53. package/src/bindings/PromClient.res +0 -72
  54. package/src/bindings/PromClient.res.mjs +0 -38
@@ -1,789 +0,0 @@
1
- module Labels = {
2
- let rec schemaIsString = (schema: S.t<'a>) =>
3
- switch schema->S.classify {
4
- | String => true
5
- | Null(s)
6
- | Option(s) =>
7
- s->schemaIsString
8
- | _ => false
9
- }
10
-
11
- let getLabelNames = (schema: S.t<'a>) =>
12
- switch schema->S.classify {
13
- | Object({items}) =>
14
- let nonStringFields = items->Array.reduce([], (nonStringFields, item) => {
15
- if item.schema->schemaIsString {
16
- nonStringFields
17
- } else {
18
- nonStringFields->Array.concat([item.location])
19
- }
20
- })
21
-
22
- switch nonStringFields {
23
- | [] => items->Array.map(item => item.location)->Ok
24
- | nonStringItems =>
25
- let nonStringItems = nonStringItems->Array.joinUnsafe(", ")
26
- Error(
27
- `Label schema must be an object with string (or optional string) values. Non string values: ${nonStringItems}`,
28
- )
29
- }
30
- | _ => Error("Label schema must be an object")
31
- }
32
- }
33
-
34
- let metricNames: Utils.Set.t<string> = Utils.Set.make()
35
-
36
- module MakeSafePromMetric = (
37
- M: {
38
- type t
39
- let make: {"name": string, "help": string, "labelNames": array<string>} => t
40
- let labels: (t, 'a) => t
41
- let handleFloat: (t, float) => unit
42
- let handleInt: (t, int) => unit
43
- },
44
- ): {
45
- type t<'a>
46
- let makeOrThrow: (~name: string, ~help: string, ~labelSchema: S.t<'a>) => t<'a>
47
- let handleInt: (t<'a>, ~labels: 'a, ~value: int) => unit
48
- let handleFloat: (t<'a>, ~labels: 'a, ~value: float) => unit
49
- let increment: (t<'a>, ~labels: 'a) => unit
50
- let incrementMany: (t<'a>, ~labels: 'a, ~value: int) => unit
51
- } => {
52
- type t<'a> = {metric: M.t, labelSchema: S.t<'a>}
53
-
54
- let makeOrThrow = (~name, ~help, ~labelSchema: S.t<'a>): t<'a> =>
55
- switch labelSchema->Labels.getLabelNames {
56
- | Ok(labelNames) =>
57
- if metricNames->Utils.Set.has(name) {
58
- JsError.throwWithMessage("Duplicate prometheus metric name: " ++ name)
59
- } else {
60
- metricNames->Utils.Set.add(name)->ignore
61
- let metric = M.make({
62
- "name": name,
63
- "help": help,
64
- "labelNames": labelNames,
65
- })
66
-
67
- {metric, labelSchema}
68
- }
69
-
70
- | Error(error) => JsError.throwWithMessage(error)
71
- }
72
-
73
- let handleFloat = ({metric, labelSchema}: t<'a>, ~labels: 'a, ~value) =>
74
- metric
75
- ->M.labels(labels->S.reverseConvertToJsonOrThrow(labelSchema))
76
- ->M.handleFloat(value)
77
-
78
- let handleInt = ({metric, labelSchema}: t<'a>, ~labels: 'a, ~value) =>
79
- metric
80
- ->M.labels(labels->S.reverseConvertToJsonOrThrow(labelSchema))
81
- ->M.handleInt(value)
82
-
83
- let increment = ({metric, labelSchema}: t<'a>, ~labels: 'a) =>
84
- (
85
- metric
86
- ->M.labels(labels->S.reverseConvertToJsonOrThrow(labelSchema))
87
- ->Obj.magic
88
- )["inc"]()
89
-
90
- let incrementMany = ({metric, labelSchema}: t<'a>, ~labels: 'a, ~value) =>
91
- (
92
- metric
93
- ->M.labels(labels->S.reverseConvertToJsonOrThrow(labelSchema))
94
- ->Obj.magic
95
- )["inc"](value)
96
- }
97
-
98
- module SafeCounter = MakeSafePromMetric({
99
- type t = PromClient.Counter.counter
100
- let make = PromClient.Counter.makeCounter
101
- let labels = PromClient.Counter.labels
102
- let handleInt = PromClient.Counter.incMany
103
- let handleFloat =
104
- PromClient.Counter.incMany->(
105
- Utils.magic: ((PromClient.Counter.counter, int) => unit) => (
106
- PromClient.Counter.counter,
107
- float,
108
- ) => unit
109
- )
110
- })
111
-
112
- module SafeGauge = MakeSafePromMetric({
113
- type t = PromClient.Gauge.gauge
114
- let make = PromClient.Gauge.makeGauge
115
- let labels = PromClient.Gauge.labels
116
- let handleInt = PromClient.Gauge.set
117
- let handleFloat = PromClient.Gauge.setFloat
118
- })
119
-
120
- module ProcessingBatch = {
121
- let loadTimeCounter = PromClient.Counter.makeCounter({
122
- "name": "envio_preload_seconds",
123
- "help": "Cumulative time spent on preloading entities during batch processing.",
124
- })
125
-
126
- let handlerTimeCounter = PromClient.Counter.makeCounter({
127
- "name": "envio_processing_seconds",
128
- "help": "Cumulative time spent executing event handlers during batch processing.",
129
- })
130
-
131
- let registerMetrics = (~loadDuration, ~handlerDuration) => {
132
- loadTimeCounter->PromClient.Counter.incMany(loadDuration->(Utils.magic: float => int))
133
- handlerTimeCounter->PromClient.Counter.incMany(handlerDuration->(Utils.magic: float => int))
134
- }
135
- }
136
-
137
- let chainIdLabelsSchema = S.object(s => {
138
- s.field("chainId", S.string->S.coerce(S.int))
139
- })
140
-
141
- module ProgressReady = {
142
- let gauge = SafeGauge.makeOrThrow(
143
- ~name="envio_progress_ready",
144
- ~help="Whether the chain is fully synced to the head.",
145
- ~labelSchema=chainIdLabelsSchema,
146
- )
147
-
148
- // Keep legacy metric name for backward compatibility
149
- let legacyGauge = PromClient.Gauge.makeGauge({
150
- "name": "hyperindex_synced_to_head",
151
- "help": "All chains fully synced",
152
- })
153
-
154
- let init = (~chainId) => {
155
- gauge->SafeGauge.handleInt(~labels=chainId, ~value=0)
156
- }
157
-
158
- let set = (~chainId) => {
159
- gauge->SafeGauge.handleInt(~labels=chainId, ~value=1)
160
- }
161
-
162
- let setAllReady = () => {
163
- legacyGauge->PromClient.Gauge.set(1)
164
- }
165
- }
166
-
167
- let handlerLabelsSchema = S.schema(s =>
168
- {
169
- "contract": s.matches(S.string),
170
- "event": s.matches(S.string),
171
- }
172
- )
173
-
174
- module ProcessingHandler = {
175
- let timeCounter = SafeCounter.makeOrThrow(
176
- ~name="envio_processing_handler_seconds",
177
- ~help="Cumulative time spent inside individual event handler executions.",
178
- ~labelSchema=handlerLabelsSchema,
179
- )
180
-
181
- let count = SafeCounter.makeOrThrow(
182
- ~name="envio_processing_handler_total",
183
- ~help="Total number of individual event handler executions.",
184
- ~labelSchema=handlerLabelsSchema,
185
- )
186
-
187
- let increment = (~contract, ~event, ~duration) => {
188
- let labels = {"contract": contract, "event": event}
189
- timeCounter->SafeCounter.handleFloat(~labels, ~value=duration)
190
- count->SafeCounter.increment(~labels)
191
- }
192
- }
193
-
194
- module PreloadHandler = {
195
- let timeCounter = SafeCounter.makeOrThrow(
196
- ~name="envio_preload_handler_seconds",
197
- ~help="Wall-clock time spent inside individual preload handler executions.",
198
- ~labelSchema=handlerLabelsSchema,
199
- )
200
-
201
- let count = SafeCounter.makeOrThrow(
202
- ~name="envio_preload_handler_total",
203
- ~help="Total number of individual preload handler executions.",
204
- ~labelSchema=handlerLabelsSchema,
205
- )
206
-
207
- let sumTimeCounter = SafeCounter.makeOrThrow(
208
- ~name="envio_preload_handler_seconds_total",
209
- ~help="Cumulative time spent inside individual preload handler executions. Can exceed wall-clock time due to parallel execution.",
210
- ~labelSchema=handlerLabelsSchema,
211
- )
212
-
213
- type operationRef = {
214
- mutable pendingCount: int,
215
- timerRef: Performance.timeRef,
216
- }
217
- let operations: dict<operationRef> = Dict.make()
218
-
219
- let makeKey = (~contract, ~event) => contract ++ ":" ++ event
220
-
221
- let startOperation = (~contract, ~event) => {
222
- let key = makeKey(~contract, ~event)
223
- switch operations->Utils.Dict.dangerouslyGetNonOption(key) {
224
- | Some(operationRef) => operationRef.pendingCount = operationRef.pendingCount + 1
225
- | None =>
226
- operations->Dict.set(
227
- key,
228
- {
229
- pendingCount: 1,
230
- timerRef: Performance.now(),
231
- },
232
- )
233
- }
234
- Performance.now()
235
- }
236
-
237
- let endOperation = (timerRef, ~contract, ~event) => {
238
- let key = makeKey(~contract, ~event)
239
- let labels = {"contract": contract, "event": event}
240
- let operationRef = operations->Dict.getUnsafe(key)
241
- operationRef.pendingCount = operationRef.pendingCount - 1
242
- if operationRef.pendingCount === 0 {
243
- timeCounter->SafeCounter.handleFloat(
244
- ~labels,
245
- ~value=operationRef.timerRef->Performance.secondsSince,
246
- )
247
- operations->Utils.Dict.deleteInPlace(key)
248
- }
249
- sumTimeCounter->SafeCounter.handleFloat(~labels, ~value=timerRef->Performance.secondsSince)
250
- count->SafeCounter.increment(~labels)
251
- }
252
- }
253
-
254
- module FetchingBlockRange = {
255
- let timeCounter = SafeCounter.makeOrThrow(
256
- ~name="envio_fetching_block_range_seconds",
257
- ~help="Cumulative time spent fetching block ranges.",
258
- ~labelSchema=chainIdLabelsSchema,
259
- )
260
-
261
- let parseTimeCounter = SafeCounter.makeOrThrow(
262
- ~name="envio_fetching_block_range_parse_seconds",
263
- ~help="Cumulative time spent parsing block range fetch responses.",
264
- ~labelSchema=chainIdLabelsSchema,
265
- )
266
-
267
- let count = SafeCounter.makeOrThrow(
268
- ~name="envio_fetching_block_range_total",
269
- ~help="Total number of block range fetch operations.",
270
- ~labelSchema=chainIdLabelsSchema,
271
- )
272
-
273
- let eventsCount = SafeCounter.makeOrThrow(
274
- ~name="envio_fetching_block_range_events_total",
275
- ~help="Cumulative number of events fetched across all block range operations.",
276
- ~labelSchema=chainIdLabelsSchema,
277
- )
278
-
279
- let sizeCounter = SafeCounter.makeOrThrow(
280
- ~name="envio_fetching_block_range_size",
281
- ~help="Cumulative number of blocks covered across all block range fetch operations.",
282
- ~labelSchema=chainIdLabelsSchema,
283
- )
284
-
285
- let increment = (
286
- ~chainId,
287
- ~totalTimeElapsed,
288
- ~parsingTimeElapsed,
289
- ~numEvents,
290
- ~blockRangeSize,
291
- ) => {
292
- timeCounter->SafeCounter.handleFloat(~labels=chainId, ~value=totalTimeElapsed)
293
- parseTimeCounter->SafeCounter.handleFloat(~labels=chainId, ~value=parsingTimeElapsed)
294
- count->SafeCounter.increment(~labels=chainId)
295
- eventsCount->SafeCounter.handleInt(~labels=chainId, ~value=numEvents)
296
- sizeCounter->SafeCounter.handleInt(~labels=chainId, ~value=blockRangeSize)
297
- }
298
- }
299
-
300
- module IndexingKnownHeight = {
301
- let gauge = SafeGauge.makeOrThrow(
302
- ~name="envio_indexing_known_height",
303
- ~help="The latest known block number reported by the active indexing source. This value may lag behind the actual chain height, as it is updated only when needed.",
304
- ~labelSchema=chainIdLabelsSchema,
305
- )
306
-
307
- let set = (~blockNumber, ~chainId) => {
308
- gauge->SafeGauge.handleInt(~labels=chainId, ~value=blockNumber)
309
- }
310
- }
311
-
312
- module Info = {
313
- let gauge = SafeGauge.makeOrThrow(
314
- ~name="envio_info",
315
- ~help="Information about the indexer",
316
- ~labelSchema=S.schema(s =>
317
- {
318
- "version": s.matches(S.string),
319
- }
320
- ),
321
- )
322
-
323
- let set = (~version) => {
324
- gauge->SafeGauge.handleInt(~labels={"version": version}, ~value=1)
325
- }
326
- }
327
-
328
- module ProcessStartTimeSeconds = {
329
- let gauge = PromClient.Gauge.makeGauge({
330
- "name": "envio_process_start_time_seconds",
331
- "help": "Start time of the process since unix epoch in seconds.",
332
- })
333
-
334
- let set = () => {
335
- gauge->PromClient.Gauge.setFloat(Date.now() /. 1000.0)
336
- }
337
- }
338
-
339
- module IndexingConcurrency = {
340
- let gauge = SafeGauge.makeOrThrow(
341
- ~name="envio_indexing_concurrency",
342
- ~help="The number of executing concurrent queries to the chain data-source.",
343
- ~labelSchema=chainIdLabelsSchema,
344
- )
345
-
346
- let set = (~concurrency, ~chainId) => {
347
- gauge->SafeGauge.handleInt(~labels=chainId, ~value=concurrency)
348
- }
349
- }
350
-
351
- module IndexingPartitions = {
352
- let gauge = SafeGauge.makeOrThrow(
353
- ~name="envio_indexing_partitions",
354
- ~help="The number of partitions used to split fetching logic by addresses and block ranges.",
355
- ~labelSchema=chainIdLabelsSchema,
356
- )
357
-
358
- let set = (~partitionsCount, ~chainId) => {
359
- gauge->SafeGauge.handleInt(~labels=chainId, ~value=partitionsCount)
360
- }
361
- }
362
-
363
- module IndexingIdleTime = {
364
- let counter = SafeCounter.makeOrThrow(
365
- ~name="envio_indexing_idle_seconds",
366
- ~help="The time the indexer source syncing has been idle. A high value may indicate the source sync is a bottleneck.",
367
- ~labelSchema=chainIdLabelsSchema,
368
- )
369
- }
370
-
371
- module IndexingSourceWaitingTime = {
372
- let counter = SafeCounter.makeOrThrow(
373
- ~name="envio_indexing_source_waiting_seconds",
374
- ~help="The time the indexer has been waiting for new blocks.",
375
- ~labelSchema=chainIdLabelsSchema,
376
- )
377
- }
378
-
379
- module IndexingQueryTime = {
380
- let counter = SafeCounter.makeOrThrow(
381
- ~name="envio_indexing_source_querying_seconds",
382
- ~help="The time spent performing queries to the chain data-source.",
383
- ~labelSchema=chainIdLabelsSchema,
384
- )
385
- }
386
-
387
- module IndexingBufferSize = {
388
- let gauge = SafeGauge.makeOrThrow(
389
- ~name="envio_indexing_buffer_size",
390
- ~help="The current number of items in the indexing buffer.",
391
- ~labelSchema=chainIdLabelsSchema,
392
- )
393
-
394
- let set = (~bufferSize, ~chainId) => {
395
- gauge->SafeGauge.handleInt(~labels=chainId, ~value=bufferSize)
396
- }
397
- }
398
-
399
- module IndexingTargetBufferSize = {
400
- let gauge = PromClient.Gauge.makeGauge({
401
- "name": "envio_indexing_target_buffer_size",
402
- "help": "The indexer-wide target buffer size shared across all chains. The actual number of items in the queue may exceed this value, but the indexer always tries to keep the buffer filled up to this target.",
403
- })
404
-
405
- let set = (~targetBufferSize) => {
406
- gauge->PromClient.Gauge.set(targetBufferSize)
407
- }
408
- }
409
-
410
- module IndexingBufferBlockNumber = {
411
- let gauge = SafeGauge.makeOrThrow(
412
- ~name="envio_indexing_buffer_block",
413
- ~help="The highest block number that has been fully fetched by the indexer.",
414
- ~labelSchema=chainIdLabelsSchema,
415
- )
416
-
417
- let set = (~blockNumber, ~chainId) => {
418
- gauge->SafeGauge.handleInt(~labels=chainId, ~value=blockNumber)
419
- }
420
- }
421
-
422
- module IndexingEndBlock = {
423
- let gauge = SafeGauge.makeOrThrow(
424
- ~name="envio_indexing_end_block",
425
- ~help="The block number to stop indexing at. (inclusive)",
426
- ~labelSchema=chainIdLabelsSchema,
427
- )
428
-
429
- let set = (~endBlock, ~chainId) => {
430
- gauge->SafeGauge.handleInt(~labels=chainId, ~value=endBlock)
431
- }
432
- }
433
-
434
- let sourceLabelsSchema = S.schema(s =>
435
- {
436
- "source": s.matches(S.string),
437
- "chainId": s.matches(S.string->S.coerce(S.int)),
438
- }
439
- )
440
-
441
- module SourceHeight = {
442
- let gauge = SafeGauge.makeOrThrow(
443
- ~name="envio_source_known_height",
444
- ~help="The latest known block number reported by the source. This value may lag behind the actual chain height, as it is updated only when queried.",
445
- ~labelSchema=sourceLabelsSchema,
446
- )
447
-
448
- let set = (~sourceName, ~chainId, ~blockNumber) => {
449
- gauge->SafeGauge.handleInt(
450
- ~labels={"source": sourceName, "chainId": chainId},
451
- ~value=blockNumber,
452
- )
453
- }
454
- }
455
-
456
- module ReorgCount = {
457
- let counter = SafeCounter.makeOrThrow(
458
- ~name="envio_reorg_detected_total",
459
- ~help="Total number of reorgs detected",
460
- ~labelSchema=chainIdLabelsSchema,
461
- )
462
-
463
- let increment = (~chain) => {
464
- counter->SafeCounter.increment(~labels=chain->ChainMap.Chain.toChainId)
465
- }
466
- }
467
-
468
- module ReorgDetectionBlockNumber = {
469
- let gauge = SafeGauge.makeOrThrow(
470
- ~name="envio_reorg_detected_block",
471
- ~help="The block number where reorg was detected the last time. This doesn't mean that the block was reorged, this is simply where we found block hash to be different.",
472
- ~labelSchema=chainIdLabelsSchema,
473
- )
474
-
475
- let set = (~blockNumber, ~chain) => {
476
- gauge->SafeGauge.handleInt(~labels=chain->ChainMap.Chain.toChainId, ~value=blockNumber)
477
- }
478
- }
479
-
480
- module ReorgThreshold = {
481
- let gauge = PromClient.Gauge.makeGauge({
482
- "name": "envio_reorg_threshold",
483
- "help": "Whether indexing is currently within the reorg threshold",
484
- })
485
-
486
- let set = (~isInReorgThreshold) => {
487
- gauge->PromClient.Gauge.set(isInReorgThreshold ? 1 : 0)
488
- }
489
- }
490
-
491
- module RollbackEnabled = {
492
- let gauge = PromClient.Gauge.makeGauge({
493
- "name": "envio_rollback_enabled",
494
- "help": "Whether rollback on reorg is enabled",
495
- })
496
-
497
- let set = (~enabled) => {
498
- gauge->PromClient.Gauge.set(enabled ? 1 : 0)
499
- }
500
- }
501
-
502
- module RollbackSuccess = {
503
- let timeCounter = PromClient.Counter.makeCounter({
504
- "name": "envio_rollback_seconds",
505
- "help": "Rollback on reorg total time.",
506
- })
507
-
508
- let counter = PromClient.Counter.makeCounter({
509
- "name": "envio_rollback_total",
510
- "help": "Number of successful rollbacks on reorg",
511
- })
512
-
513
- let eventsCounter = PromClient.Counter.makeCounter({
514
- "name": "envio_rollback_events",
515
- "help": "Number of events rollbacked on reorg",
516
- })
517
-
518
- let increment = (~timeSeconds: float, ~rollbackedProcessedEvents: float) => {
519
- timeCounter->PromClient.Counter.incMany(timeSeconds->(Utils.magic: float => int))
520
- counter->PromClient.Counter.inc
521
- eventsCounter->PromClient.Counter.incMany(rollbackedProcessedEvents->Utils.floatToInt)
522
- }
523
- }
524
-
525
- module RollbackHistoryPrune = {
526
- let entityNameLabelsSchema = S.object(s => s.field("entity", S.string))
527
-
528
- let timeCounter = SafeCounter.makeOrThrow(
529
- ~name="envio_rollback_history_prune_seconds",
530
- ~help="The total time spent pruning entity history which is not in the reorg threshold.",
531
- ~labelSchema=entityNameLabelsSchema,
532
- )
533
-
534
- let counter = SafeCounter.makeOrThrow(
535
- ~name="envio_rollback_history_prune_total",
536
- ~help="Number of successful entity history prunes",
537
- ~labelSchema=entityNameLabelsSchema,
538
- )
539
-
540
- let increment = (~timeSeconds, ~entityName) => {
541
- timeCounter->SafeCounter.handleFloat(~labels={entityName}, ~value=timeSeconds)
542
- counter->SafeCounter.increment(~labels={entityName})
543
- }
544
- }
545
-
546
- module RollbackTargetBlockNumber = {
547
- let gauge = SafeGauge.makeOrThrow(
548
- ~name="envio_rollback_target_block",
549
- ~help="The block number reorg was rollbacked to the last time.",
550
- ~labelSchema=chainIdLabelsSchema,
551
- )
552
-
553
- let set = (~blockNumber, ~chain) => {
554
- gauge->SafeGauge.handleInt(~labels=chain->ChainMap.Chain.toChainId, ~value=blockNumber)
555
- }
556
- }
557
-
558
- module ProcessingMaxBatchSize = {
559
- let gauge = PromClient.Gauge.makeGauge({
560
- "name": "envio_processing_max_batch_size",
561
- "help": "The maximum number of items to process in a single batch.",
562
- })
563
-
564
- let set = (~maxBatchSize) => {
565
- gauge->PromClient.Gauge.set(maxBatchSize)
566
- }
567
- }
568
-
569
- module ProgressBlockNumber = {
570
- let gauge = SafeGauge.makeOrThrow(
571
- ~name="envio_progress_block",
572
- ~help="The block number of the latest block processed and stored in the database.",
573
- ~labelSchema=chainIdLabelsSchema,
574
- )
575
-
576
- let set = (~blockNumber, ~chainId) => {
577
- gauge->SafeGauge.handleInt(~labels=chainId, ~value=blockNumber)
578
- }
579
- }
580
-
581
- module ProgressEventsCount = {
582
- let gauge = SafeGauge.makeOrThrow(
583
- ~name="envio_progress_events",
584
- ~help="The number of events processed and reflected in the database.",
585
- ~labelSchema=chainIdLabelsSchema,
586
- )
587
-
588
- let set = (~processedCount: float, ~chainId) => {
589
- gauge->SafeGauge.handleFloat(~labels=chainId, ~value=processedCount)
590
- }
591
- }
592
-
593
- module ProgressLatency = {
594
- let gauge = SafeGauge.makeOrThrow(
595
- ~name="envio_progress_latency",
596
- ~help="The latency in milliseconds between the latest processed event creation and the time it was written to storage.",
597
- ~labelSchema=chainIdLabelsSchema,
598
- )
599
-
600
- let set = (~latencyMs, ~chainId) => {
601
- gauge->SafeGauge.handleInt(~labels=chainId, ~value=latencyMs)
602
- }
603
- }
604
-
605
- let effectLabelsSchema = S.object(s => {
606
- s.field("effect", S.string)
607
- })
608
-
609
- // For metrics whose backing state lives per scope ("crossChain" or a chain
610
- // id) — without the label, scopes of the same effect would clobber each
611
- // other's gauge value.
612
- let effectScopeLabelsSchema = S.schema(s =>
613
- {
614
- "effect": s.matches(S.string),
615
- "scope": s.matches(S.string),
616
- }
617
- )
618
-
619
- module EffectCalls = {
620
- let timeCounter = SafeCounter.makeOrThrow(
621
- ~name="envio_effect_call_seconds",
622
- ~help="Processing time taken to call the Effect function.",
623
- ~labelSchema=effectScopeLabelsSchema,
624
- )
625
-
626
- let sumTimeCounter = SafeCounter.makeOrThrow(
627
- ~name="envio_effect_call_seconds_total",
628
- ~help="Cumulative time spent calling the Effect function during the indexing process.",
629
- ~labelSchema=effectScopeLabelsSchema,
630
- )
631
-
632
- let totalCallsCount = SafeCounter.makeOrThrow(
633
- ~name="envio_effect_call_total",
634
- ~help="Cumulative number of resolved Effect function calls during the indexing process.",
635
- ~labelSchema=effectScopeLabelsSchema,
636
- )
637
-
638
- let activeCallsCount = SafeGauge.makeOrThrow(
639
- ~name="envio_effect_active_calls",
640
- ~help="The number of Effect function calls that are currently running.",
641
- ~labelSchema=effectScopeLabelsSchema,
642
- )
643
- }
644
-
645
- module EffectCacheCount = {
646
- let gauge = SafeGauge.makeOrThrow(
647
- ~name="envio_effect_cache",
648
- ~help="The number of items in the effect cache.",
649
- ~labelSchema=effectScopeLabelsSchema,
650
- )
651
-
652
- let set = (~count, ~effectName, ~scope) => {
653
- gauge->SafeGauge.handleInt(~labels={"effect": effectName, "scope": scope}, ~value=count)
654
- }
655
- }
656
-
657
- module EffectCacheInvalidationsCount = {
658
- let counter = SafeCounter.makeOrThrow(
659
- ~name="envio_effect_cache_invalidations",
660
- ~help="The number of effect cache invalidations.",
661
- ~labelSchema=effectLabelsSchema,
662
- )
663
-
664
- let increment = (~effectName) => {
665
- counter->SafeCounter.increment(~labels=effectName)
666
- }
667
- }
668
-
669
- module EffectQueueCount = {
670
- let gauge = SafeGauge.makeOrThrow(
671
- ~name="envio_effect_queue",
672
- ~help="The number of effect calls waiting in the rate limit queue.",
673
- ~labelSchema=effectScopeLabelsSchema,
674
- )
675
-
676
- let timeCounter = SafeCounter.makeOrThrow(
677
- ~name="envio_effect_queue_wait_seconds",
678
- ~help="The time spent waiting in the rate limit queue.",
679
- ~labelSchema=effectLabelsSchema,
680
- )
681
-
682
- let set = (~count, ~effectName, ~scope) => {
683
- gauge->SafeGauge.handleInt(~labels={"effect": effectName, "scope": scope}, ~value=count)
684
- }
685
- }
686
-
687
- module StorageLoad = {
688
- let loadLabelsSchema = S.schema(s =>
689
- {
690
- "operation": s.matches(S.string),
691
- "storage": s.matches(S.string),
692
- }
693
- )
694
-
695
- let timeCounter = SafeCounter.makeOrThrow(
696
- ~name="envio_storage_load_seconds",
697
- ~help="Processing time taken to load data from storage.",
698
- ~labelSchema=loadLabelsSchema,
699
- )
700
-
701
- let sumTimeCounter = SafeCounter.makeOrThrow(
702
- ~name="envio_storage_load_seconds_total",
703
- ~help="Cumulative time spent loading data from storage during the indexing process.",
704
- ~labelSchema=loadLabelsSchema,
705
- )
706
-
707
- let counter = SafeCounter.makeOrThrow(
708
- ~name="envio_storage_load_total",
709
- ~help="Cumulative number of successful storage load operations during the indexing process.",
710
- ~labelSchema=loadLabelsSchema,
711
- )
712
-
713
- let whereSizeCounter = SafeCounter.makeOrThrow(
714
- ~name="envio_storage_load_where_size",
715
- ~help="Cumulative number of filter conditions ('where' items) used in storage load operations during the indexing process.",
716
- ~labelSchema=loadLabelsSchema,
717
- )
718
-
719
- let sizeCounter = SafeCounter.makeOrThrow(
720
- ~name="envio_storage_load_size",
721
- ~help="Cumulative number of records loaded from storage during the indexing process.",
722
- ~labelSchema=loadLabelsSchema,
723
- )
724
-
725
- type operationRef = {
726
- mutable pendingCount: int,
727
- timerRef: Performance.timeRef,
728
- }
729
- let operations = Dict.make()
730
-
731
- let makeKey = (~storage, ~operation) => storage ++ ":" ++ operation
732
-
733
- let startOperation = (~storage, ~operation) => {
734
- let key = makeKey(~storage, ~operation)
735
- switch operations->Utils.Dict.dangerouslyGetNonOption(key) {
736
- | Some(operationRef) => operationRef.pendingCount = operationRef.pendingCount + 1
737
- | None =>
738
- operations->Dict.set(
739
- key,
740
- (
741
- {
742
- pendingCount: 1,
743
- timerRef: Performance.now(),
744
- }: operationRef
745
- ),
746
- )
747
- }
748
- Performance.now()
749
- }
750
-
751
- let endOperation = (timerRef, ~storage, ~operation, ~whereSize, ~size) => {
752
- let key = makeKey(~storage, ~operation)
753
- let labels = {"operation": operation, "storage": storage}
754
- let operationRef = operations->Dict.getUnsafe(key)
755
- operationRef.pendingCount = operationRef.pendingCount - 1
756
- if operationRef.pendingCount === 0 {
757
- timeCounter->SafeCounter.handleFloat(
758
- ~labels,
759
- ~value=operationRef.timerRef->Performance.secondsSince,
760
- )
761
- operations->Utils.Dict.deleteInPlace(key)
762
- }
763
- sumTimeCounter->SafeCounter.handleFloat(~labels, ~value=timerRef->Performance.secondsSince)
764
- counter->SafeCounter.increment(~labels)
765
- whereSizeCounter->SafeCounter.handleInt(~labels, ~value=whereSize)
766
- sizeCounter->SafeCounter.handleInt(~labels, ~value=size)
767
- }
768
- }
769
-
770
- module StorageWrite = {
771
- let storageLabelsSchema = S.object(s => s.field("storage", S.string))
772
-
773
- let timeCounter = SafeCounter.makeOrThrow(
774
- ~name="envio_storage_write_seconds",
775
- ~help="Cumulative time spent writing batch data to storage.",
776
- ~labelSchema=storageLabelsSchema,
777
- )
778
-
779
- let counter = SafeCounter.makeOrThrow(
780
- ~name="envio_storage_write_total",
781
- ~help="Cumulative number of successful storage write operations during the indexing process.",
782
- ~labelSchema=storageLabelsSchema,
783
- )
784
-
785
- let increment = (~storage, ~timeSeconds) => {
786
- timeCounter->SafeCounter.handleFloat(~labels={storage}, ~value=timeSeconds)
787
- counter->SafeCounter.increment(~labels={storage})
788
- }
789
- }