Filecoin logo

Filecoin

Dealbot Events & Metrics

Dealbot Methodology

This document is the intended source of truth for the events emitted by dealbot checks and the metrics computed from them. It is intended for dealbot dashboard consumers and maintainers who need to understand what each metric means and where it comes from.

Note on "events": the entries in the Event List are named timing markers used to define metric Timer Starts/Ends — they are not all emitted as discrete Prometheus events or log lines. Each marker is anchored in code (as a timestamp variable, log line, or status transition) and used to compute the metrics in the Metrics section.

Rendered from the dealbot documentation · cached for 24 hours

Data Storage Event Model

Below are the sequence of events for a Data Storage check. The Data Storage flow is used because it encapsulates a Retrieval check as well.

Data Storage Event Timeline

sequenceDiagram
  autonumber
  participant Dealbot
  participant SP as PDP Storage Provider
  participant RPC as Chain RPC Provider
  participant FPNI as filecoinpin.contact IPNI Instance
  participant CPNI as cid.contact IPNI Instance

  rect rgba(120, 120, 200, 0.15)
    %% Data Storage Only
    Dealbot->>SP: uploadToSpStart
    SP-->>Dealbot: uploadToSpEnd (2xx, piece CID)
    Dealbot-->>Dealbot: dealCreated (upload result returned)
    SP-->>Dealbot: pieceAdded (tx hash, async)
    RPC-->>Dealbot: pieceConfirmed (async)
    SP-->>Dealbot: spIndexingComplete
    SP-->>Dealbot: spAnnouncedAdvertisementToIpni
  end

  Dealbot->>FPNI: ipniVerificationStart (filecoinpin.contact)
  FPNI-->>Dealbot: ipniVerificationComplete (filecoinpin.contact)
  opt filecoinpin.contact verified
    Dealbot->>CPNI: ipniVerificationStart (cid.contact)
    CPNI-->>Dealbot: ipniVerificationComplete (cid.contact)
  end
  Dealbot-->>SP: ipfsRetrievalStart
  SP-->>Dealbot: ipfsRetrievalFirstByteReceived
  SP-->>Dealbot: ipfsRetrievalLastByteReceived
  Dealbot-->>Dealbot: ipfsRetrievalIntegrityChecked

Event List

Event Definition Relevant Checks Source of truth
uploadToSpStart Dealbot is about to start an upload attempt for a piece to an SP. Data Storage deal.service.ts (anchor: deal.uploadStartTime)
uploadToSpEnd Upload finished (success with HTTP 2xx, failure). Data Storage deal.service.ts (handleStored)
dealCreated Deal reaches DealStatus.DEAL_CREATED after all sub-checks (upload, onchain, IPNI, retrieval) succeed. Upload completion alone sets DealStatus.UPLOADED, not DEAL_CREATED. Data Storage deal.service.ts
pieceAdded Piece submission is recorded on-chain. Driven by Synapse piecesAdded progress event; transaction hash is known. Data Storage deal.service.ts
pieceConfirmed Piece is confirmed on-chain. Driven by Synapse piecesConfirmed progress event. Data Storage deal.service.ts (sets piecesConfirmedTime, observes pieceConfirmedOnChainMs histogram)
spIndexingComplete By polling SP, dealbot learned SP has indexed the piece locally (indexed=true). When the SP returns indexedAt, dealbot uses that SP timestamp; otherwise it uses the local poll time. Data Storage ipni.strategy.ts
spAnnouncedAdvertisementToIpni By polling SP, dealbot learned SP has announced the advertisement to IPNI (advertised=true). When the SP returns advertisedAt, dealbot uses that SP timestamp; otherwise it uses the local poll time. Data Storage ipni.strategy.ts
ipniVerificationStart Dealbot begins polling an IPNI indexer for a provider record. Occurs once per indexer: filecoinpin.contact first, then cid.contact only after filecoinpin.contact succeeds. This event anchors ipniVerifyMs timer starts: for Data Storage {indexer="filecoinpin.contact"}, prefer the SP's advertisedAt when available and sane (otherwise the local time dealbot observed advertised=true while polling the SP; if no advertisement timestamp exists, fall back to this polling-start time). For Data Storage {indexer="cid.contact"}, use filecoinpin.contact verification completion. Retrieval checks always anchor from this local polling-start time. Data Storage, Retrieval ipni.strategy.ts, ipni-verification.service.ts
ipniVerificationComplete An IPNI indexer call completes (pass or timeout). Occurs once per indexer: filecoinpin.contact always, cid.contact only after filecoinpin.contact verified. Data Storage, Retrieval ipni.strategy.ts
ipfsRetrievalStart Dealbot to SP /ipfs/ retrieval begins. Data Storage, Retrieval retrieval-addons.service.ts (anchor: retrieval startTime; logs retrieval_started)
ipfsRetrievalFirstByteReceived First byte received from /ipfs/{rootCid}. Data Storage, Retrieval retrieval-addons.service.ts (drives ipfsRetrievalFirstByteMs)
ipfsRetrievalLastByteReceived Last byte received from /ipfs/{rootCid}. Data Storage, Retrieval retrieval-addons.service.ts (drives ipfsRetrievalLastByteMs)
ipfsRetrievalIntegrityChecked Retrieved content matches expected CID (per-block sha256 hash verification via createBlock). Inline check at end of DAG traversal; no discrete event emission. Data Storage, Retrieval ipfs-block.strategy.ts

Pull Check Event Model

Below are the events for a Pull Check. Pull checks reverse the data flow of the Data Storage check: instead of dealbot uploading bytes, it asks the SP to pull bytes from a temporary /api/piece/{pieceCid} URL.

Pull Check Event Timeline

sequenceDiagram
  autonumber
  participant Dealbot
  participant SP as PDP Storage Provider
  participant RPC as Chain RPC Provider

  Dealbot->>Dealbot: hostedPieceRegistered
  Dealbot->>SP: pullRequestSubmittedToSp (pullPieces)
  SP-->>Dealbot: pullRequestAcknowledgedBySp
  SP-->>Dealbot: pullRequestStartedBySp
  Dealbot->>SP: pullStatusPolled (waitForPullPieces, repeated)
  SP-->>Dealbot: pullRequestIsTerminal
  Dealbot->>SP: directPieceFetchStarted (/piece/{cid})
  SP-->>Dealbot: directPieceFetchCompleted
  Dealbot-->>Dealbot: pullRequestIntegrityChecked

Pull Check Event List

Event Definition Implemented Source of truth
pullRequestSubmittedToSp Dealbot calls Synapse pullPiece (POST /pdp/piece/pull) against the SP for the registered piece CID. Yes pull-check.service.ts
pullRequestAcknowledgedBySp SP returns from pullPieces (success or non-terminal-failure). Yes pull-check.service.ts
pullRequestStartedBySp Dealbot receives SP request for /api/piece/{pieceCid} from dealbot. Recorded once per registration. Yes pull-piece.controller.ts
pullRequestIsTerminal Dealbot determines the pull request is in terminal pull status (complete, failed, ...) via waitForPullPieces or the polling operation has timed out. Intermediate poll statuses are not counted. Yes pull-check.service.ts
pullRequestIntegrityChecked Dealbot completed direct /piece/{pieceCid} retrieval from the SP and confirmed the bytes match the pieceCid. Yes pull-check.service.ts

Sampled Retrieval Check Event Model

Below are the events for an Sampled Retrieval check. Unlike the Data Storage flow, sampled retrieval is a single-shot per-piece flow: select a publicly-discoverable piece from the FWSS subgraph → fetch the piece from the SP → optionally parse the CAR, verify IPNI, and sample block fetches → write one row to ClickHouse. The check emits one row to sampled_retrieval_checks even on abort or unexpected error, so partial timing/byte evidence is never lost.

Sampled Retrieval Check Event Timeline

sequenceDiagram
  autonumber
  participant Dealbot
  participant Subgraph as Subgraph
  participant SP as Storage Provider
  participant IPNI as filecoinpin.contact

  Dealbot->>Subgraph: sampledPieceSelectionStart
  Subgraph-->>Dealbot: sampledPieceSelected
  Dealbot->>SP: sampledPieceFetchStart (GET /piece/{pieceCid})
  SP-->>Dealbot: sampledPieceFetchFirstByteReceived
  SP-->>Dealbot: sampledPieceFetchLastByteReceived
  Dealbot-->>Dealbot: sampledCommPVerified

  opt if piece advertises IPFS indexing
    Dealbot-->>Dealbot: sampledCarParsed
    Dealbot->>IPNI: sampledIpniVerificationStart
    IPNI-->>Dealbot: sampledIpniVerificationComplete
    Dealbot->>SP: sampledBlockFetchStart (GET /ipfs/{cid}?format=raw, sampled)
    SP-->>Dealbot: sampledBlockFetchComplete
  end

  Dealbot-->>Dealbot: sampledRetrievalCheckComplete

Sampled Retrieval Check Event List

Event Definition Source of truth
sampledPieceSelectionStart Dealbot begins selecting a sampled piece for the SP under test from Dealbot's subgraph (size-bucket + indexed/any pool sampling with fallbacks). sampled-piece-selector.service.ts
sampledPieceSelected Subgraph returned a candidate piece (or all fallbacks were exhausted and the check is recorded as skipped). sampled-piece-selector.service.ts
sampledPieceFetchStart Dealbot initiates GET {spBaseUrl}/piece/{pieceCid}. piece-retrieval.service.ts (logs sampledRetrieval_started)
sampledPieceFetchFirstByteReceived First byte received from /piece/{pieceCid}. piece-retrieval.service.ts (drives sampledPieceRetrievalFirstByteMs)
sampledPieceFetchLastByteReceived Last byte received from /piece/{pieceCid}. piece-retrieval.service.ts (drives sampledPieceRetrievalLastByteMs)
sampledCommPVerified Response bytes hashed and the resulting CommP compared against the declared pieceCid. Inline check; no discrete event emission. Failure flips piece fetch to failure.commp. piece-retrieval.service.ts
sampledCarParsed Fetched piece bytes are parsed as a CAR and a random sample of SAMPLED_RETRIEVAL_BLOCK_SAMPLE_COUNT CIDs is selected. Only emitted when the piece advertises IPFS indexing. piece-validation.service.ts
sampledIpniVerificationStart Dealbot begins polling filecoinpin.contact for <rootCid + sampled CIDs, SP> provider records. piece-validation.service.ts
sampledIpniVerificationComplete IPNI verification finishes (all CIDs resolved to the SP, IPNI_VERIFICATION_TIMEOUT_MS reached, or error). piece-validation.service.ts (drives ipni_verify_ms)
sampledBlockFetchStart Dealbot starts fetching the sampled CIDs via GET {spBaseUrl}/ipfs/{cid}?format=raw. piece-validation.service.ts
sampledBlockFetchComplete All sampled block fetches finished; each response was hash-verified against its declared CID (any non-2xx, hash mismatch, unsupported codec, a timeout, or transport error counts as a failed block). piece-validation.service.ts
sampledRetrievalCheckComplete Sampled retrieval check terminates — successful piece fetch (plus optional CAR/IPNI/block-fetch validations) or any failure / abort / timeout. Drives the sampled_retrieval_checks ClickHouse row and sampledRetrievalCheckMs. sampled-retrieval.service.ts (logs sampledRetrieval_completed)

Metrics

  • Many of the metrics below are derived from the events above.
  • They are exported via Prometheus.
  • All Prometheus/OpenTelemetry metrics have label/attributes for:
  • network=calibration|mainnet
  • checkType=dataStorage|retrieval|sampledRetrieval|dataRetention|dataSetCreation|dataSetLifecycleCheck|pullCheck — attribute metrics to a particular check/job
  • providerId — attribute metrics to a particular SP
  • providerName — human-readable name of the SP (defaults to "unknown" when not available)
  • providerStatus=approved|unapproved — attribute metrics to only approved SPs for example
Metric Relevant Checks Timer Starts Timer Ends Additional Info Source of truth
ingestMs Data Storage uploadToSpStart uploadToSpEnd deal.service.ts
ingestThroughputBps Data Storage n/a n/a (uploadedPieceBytes / ingestMs) * 1000 deal.service.ts
pieceAddedOnChainMs Data Storage uploadToSpEnd pieceAdded deal.service.ts
pieceConfirmedOnChainMs Data Storage pieceAdded pieceConfirmed deal.service.ts
spIndexLocallyMs Data Storage uploadToSpEnd spIndexingComplete ipni.strategy.ts
spAnnounceAdvertisementMs Data Storage uploadToSpEnd spAnnouncedAdvertisementToIpni ipni.strategy.ts
ipniVerifyMs Data Storage, Retrieval ipniVerificationStart ipniVerificationComplete One histogram observation per indexer call. Extra labels: value (success, or failure.* — same vocabulary as Discoverability Status for filecoinpin.contact; cid.contact Verification Status for cid.contact) and indexer (filecoinpin.contact or cid.contact). Filter {value="success", indexer="filecoinpin.contact"} for advertisement-to-filecoinpin.contact latency. The cid.contact observation is only emitted after filecoinpin.contact succeeds. Timer-start rules: ipniVerificationStart. ipni.strategy.ts, retrieval.service.ts
ipfsRetrievalFirstByteMs Data Storage, Retrieval ipfsRetrievalStart ipfsRetrievalFirstByteReceived retrieval.service.ts
ipfsRetrievalBlockFirstByteMs Data Storage, Retrieval Each IPFS block request First byte received for each block Emitted for block-fetch retrievals (one observation per block) retrieval.service.ts
ipfsRetrievalLastByteMs Data Storage, Retrieval ipfsRetrievalStart ipfsRetrievalLastByteReceived retrieval.service.ts
ipfsRetrievalThroughputBps Data Storage, Retrieval n/a n/a (downloadedCarBytes / ipfsRetrievalLastByteMs) * 1000 retrieval.service.ts
dataStorageCheckMs Data Storage uploadToSpStart ipfsRetrievalIntegrityChecked Duration of a Data Storage check
retrievalCheckMs Retrieval Retrieval check start ipfsRetrievalIntegrityChecked Duration of a Retrieval check
dataSetCreationMs Data-Set Creation Data-set creation uploadToSpStart Data-set creation pieceConfirmed Duration of one data-set creation with confirmed piece (all using createDataSetWithPiece) deal.service.ts
dataSetLifecycleCheckMs Data-Set Lifecycle Check Both variants start (parallel) Both variants settle Wall-clock duration of the full parallel execution (both empty and with-pieces variants). Emitted on success and failure.timedout only. See data-set-lifecycle-check.md. data-set-lifecycle.service.ts
pullRequestAcknowledgementLatencyMs Pull pullRequestSubmittedToSp pullRequestAcknowledgedBySp Time from pullPieces submission to SP request acknowledgement. pull-check.service.ts
pullRequestStartedMs Pull pullRequestSubmittedToSp pullRequestStartedBySp Time from pullPieces submission to the SP reading the first byte of /api/piece/{pieceCid}. Skipped (no observation) when the SP never fetches from dealbot. pull-check.service.ts, pull-piece.controller.ts
pullRequestCompletionLatencyMs Pull pullRequestSubmittedToSp pullRequestIsTerminal Time from pullPieces submission to terminal SP pull status. Emitted once for the check, either on success or failure. pull-check.service.ts
pullRequestThroughputBps Pull n/a n/a (pieceSizeBytes / pullRequestCompletionLatencyMs) * 1000. Upper-bound on actual transfer rate because pullRequestCompletionLatencyMs includes SP-side scheduling and dealbot's polling cadence. pull-check.service.ts
sampledPieceRetrievalFirstByteMs Sampled Retrieval sampledPieceFetchStart sampledPieceFetchFirstByteReceived Time to first byte for sampled piece retrievals sampled-retrieval.service.ts
sampledPieceRetrievalLastByteMs Sampled Retrieval sampledPieceFetchStart sampledPieceFetchLastByteReceived Total time to retrieve a sampled piece sampled-retrieval.service.ts
sampledPieceRetrievalThroughputBps Sampled Retrieval n/a n/a (bytesRetrieved / sampledPieceRetrievalLastByteMs) * 1000 sampled-retrieval.service.ts
sampledRetrievalCheckMs Sampled Retrieval sampledPieceSelected sampledRetrievalCheckComplete End-to-end sampled retrieval check duration (excludes piece selection; includes CAR/IPNI/block-fetch validation when applicable). Emitted even on abort. sampled-retrieval.service.ts
  • These count metrics are used to track the occurrence of a particular status for a check.
  • All Prometheus/OpenTelemetry status count metrics have additional label/attributes for:
  • value - attribute counts to different outcomes.
    • Note: this is an ambiguous and confusing label/tag. It isn't to be confused with the metric counter's value. In retrospect, this should have been called something like status instead to avoid confusion with first class value term for metrics. The presence of this confusing value label causes Clickhouse metric queries to have label('value') and value_avg.
  • Most of these count metrics emit a counter value of 1. Exceptions are noted below in the Counter Value column.
Metric Relevant Checks When Emitted In Successful Case value Label Values Additional Info Counter Value Source of truth
dataStorageUploadStatus Data Storage uploadToSpEnd success, failure.timedout, failure.other from Data Storage Sub-status meanings. 1
dataStorageOnchainStatus Data Storage pieceConfirmed success, failure.timedout, failure.other from Data Storage Sub-status meanings. 1 deal.service.ts
dataStorageStatus Data Storage When the Data Storage check completes (all four sub-statuses done) success, failure.timedout, failure.other from Deal Status Progression. 1 deal.service.ts
discoverabilityStatus Data Storage, Retrieval ipniVerificationComplete success, failure.timedout, failure.other, skipped from Data Storage Sub-status meanings. Driven exclusively by the filecoinpin.contact result; cid.contact outcome is tracked separately in cidContactVerification. 1
cidContactVerification Data Storage ipniVerificationComplete for the cid.contact call (or when cid.contact is bypassed) success, failure.timedout, failure.other, skipped from cid.contact Verification Status. Emitted once per check. skipped when filecoinpin.contact did not reach success (including discoverability skipped or failure.*); otherwise reflects the cid.contact poll outcome. Does not affect overall Data Storage check status. 1 ipni.strategy.ts
ipfsRetrievalHttpResponseCode Data Storage, Retrieval ipfsRetrievalLastByteReceived 200, 500, 2xxSuccess, 4xxClientError, 5xxServerError, otherHttpStatusCodes, failure 1 retrieval.service.ts
retrievalStatus Data Storage, Retrieval ipfsRetrievalIntegrityChecked success, failure.timedout, failure.other from Data Storage Sub-status meanings. On the Retrieval path, the pre-flight branches on the on-chain PDPVerifier.pieceLive(dataSetId, pieceId) result. When pieceLive=false (dataset terminated, piece never created, or piece hard-removed), skipped.piece_missing is emitted and the deal is marked cleaned_up=true; no SP probe runs. When pieceLive=true and the SP returns 404 on /pdp/piece/:pieceCid/status, failure.other is emitted and a failed retrieval row is recorded (deal stays in the candidate pool for re-probing). 1
dataSetCreationStatus Data-Set Creation Not tied to an event above but rather to data-set creation start (pending) and completion (success/failure.*) pending, success, failure.timedout, failure.other 1 deal.service.ts
dataSetLifecycleCheckStatus Data-Set Lifecycle Check When a data_set_lifecycle_check invocation finishes (after both variants settle) success, failure.timedout, failure.other success requires both variants to pass: createDataSetterminateService (empty) and uploadPieceStreamingfindPiececreateDataSetAndAddPiecesterminateService (with-pieces). failure.* means at least one variant failed; per-variant outcome is in the log lines. See data-set-lifecycle-check.md. 1 data-set-lifecycle.service.ts
dataSetChallengeStatus Data Retention Emitted on each Data Retention Check poll when a provider's confirmed proving-period totals advance (strictly positive deltas since the last poll). success (challenges in newly confirmed successful proving periods), failure (challenges in newly confirmed faulted periods) Counter increment = period delta × 5 (CHALLENGES_PER_PROVING_PERIOD). Period delta is the increase in subgraph-confirmed proving periods since the previous poll for that provider (not "challenges per poll" in the abstract). See data-retention.md §3. data-retention.service.ts
pullRequestProviderStatus Pull When the SP reports a terminal pull status via waitForPullPieces. Recorded exactly once per check (intermediate poll statuses are not counted). Raw SP-reported pull status, for example complete, failed, not_found. Use this to separate SP-side pull failures from dealbot-side validation failures. 1 pull-check.service.ts
pullCheckStatus Pull When the Pull Check terminates (success after direct piece validation, or any failure). Recorded exactly once per check. success, failure.timedout, failure.other from Pull Check Status. 1 pull-check.service.ts
sampledPieceRetrievalStatus Sampled Retrieval sampledRetrievalCheckComplete success, skipped, failure.http, failure.commp, failure.timedout, failure.other from Sampled Retrieval Sub-status meanings. sampled-retrieval.service.ts
sampledPieceHttpResponseCode Sampled Retrieval sampledPieceFetchLastByteReceived Same as ipfsRetrievalHttpResponseCode. sampled-retrieval.service.ts
sampledCarParseStatus Sampled Retrieval sampledCarParsed, or when CAR parsing didn't run (records skipped) success, skipped, failure.not_parseable from Sampled Retrieval Sub-status meanings. sampled-retrieval.service.ts
sampledIpniStatus Sampled Retrieval sampledIpniVerificationComplete, or when piece fetch failed (records skipped) success, skipped, failure.timedout, failure.other from Sampled Retrieval Sub-status meanings. sampled-retrieval.service.ts
sampledBlockFetchStatus Sampled Retrieval sampledBlockFetchComplete, or when piece fetch failed (records skipped) success, skipped, failure.other from Sampled Retrieval Sub-status meanings. sampled-retrieval.service.ts

Other Gauges

Unlike the count metrics above, gauges below expose a level (for example overdue proving periods right now). They do not use the value outcome label. The scraped sample magnitude is the "Gauge Value" measurement.

Metric Relevant Checks When Emitted Gauge Value Source of truth
pdp_provider_estimated_overdue_periods Data Retention Emitted on every Data Retention Check poll for every successfully processed provider. Number of overdue proving periods (non-negative integer) data-retention.service.ts

ClickHouse Tables

When CLICKHOUSE_URL is configured, dealbot writes one row per check result to ClickHouse for long-term storage and analysis. All tables are partitioned by month with a 1-year TTL.

Source of truth: the DDL and column-level comments in clickhouse.schema.ts are authoritative. The summary below is for orientation only.

All tables share the primary key (probe_location, sp_address, timestamp):

  • probe_location - identifies which dealbot instance produced the row, allowing multiple deployments to be distinguished in queries (set via DEALBOT_PROBE_LOCATION)
  • sp_address - the Ethereum/FEVM address of the storage provider under test
  • timestamp - when the row was written (milliseconds UTC)
Back to Onchain Cloud