Skip to content

chore: migrate motoko/query_stats to icp-cli - #1364

Merged
raymondk merged 21 commits into
masterfrom
chore/migrate-query-stats-to-icp-cli
Jun 11, 2026
Merged

chore: migrate motoko/query_stats to icp-cli#1364
raymondk merged 21 commits into
masterfrom
chore/migrate-query-stats-to-icp-cli

Conversation

@marc0olo

@marc0olo marc0olo commented Jun 10, 2026

Copy link
Copy Markdown
Member

Summary

Migrates motoko/query_stats from dfx to icp-cli.

  • Replace dfx.json with icp.yaml (@dfinity/motoko@v5.0.0)
  • Move src/query_stats_backend/main.mobackend/app.mo; rename actor to QueryStats
  • Replace inline actor "aaaaa-aa" with import { ic } "mo:ic" (mo:ic 4.0.0); add Nat import
  • Update mops.toml: moc 1.9.0, core 2.5.0, ic 4.0.0, --default-persistent-actors
  • Add icp.yaml, CI workflow (icp-dev-env-motoko:0.3.2)
  • Add two Makefile targets:
    • make test — fast structural check (CI); verifies all four stat field names are present; stats show 0 due to aggregation delay
    • make test-stats — full demonstration; polls every 3s with 13 --query calls per round until non-zero stats appear (up to 30s)

How query stats work locally (non-obvious)

Three requirements for stats to appear on a local PocketIC replica:

  1. Use --queryicp canister call makes update calls by default; only query calls are tracked in query_stats
  2. 13+ calls per round — PocketIC simulates a 13-node subnet with integer division (num_calls / 13); fewer than 13 calls round to zero
  3. Continuous queries across epoch boundariesset_epoch_from_height is only invoked during query execution; queries must keep running so epoch transitions flush accumulated stats into the payload pipeline (sleeping without queries leaves stats unflushed regardless of how long you wait)

Test plan

  • motoko-query_stats CI passes (make test)
  • make test-stats shows non-zero Number of calls within 30s

🤖 Generated with Claude Code

marc0olo and others added 16 commits June 10, 2026 17:15
Replace dfx.json with icp.yaml, update mops.toml to current toolchain
versions (moc 1.9.0, core 2.5.0, ic 4.0.0), replace inline management
canister actor type with `import { ic } "mo:ic"`, move source to
backend/app.mo, add Makefile with numbered tests, CI workflow, and
updated README.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…local replica

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…cted locally

Query stats require 120+ blocks to aggregate on local PocketIC (2 epochs × 60
blocks). Values are always 0 locally — this is correct IC behavior, not a bug.
Non-zero values appear on IC mainnet after enough queries accumulate.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
icp canister call makes UPDATE calls by default. UPDATE calls to query
functions are NOT counted in query_stats.num_calls_total — only actual
QUERY calls are tracked. Adding --query ensures the calls are recorded.

The 2-epoch aggregation delay (120 blocks × 100ms ≈ 12s) still means
the first run shows 0; the second run shows non-zero values from run 1.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- make test: fast structural check (CI), stats show 0 due to lag
- make test-stats: generates load, waits ~20s for 2-epoch aggregation,
  verifies non-zero values — the full end-to-end demonstration
- Use --query flag on load() calls (update calls not counted in query_stats)
- README: document both targets, explain timing (2 epochs × 60 blocks × 100ms)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@marc0olo
marc0olo marked this pull request as ready for review June 11, 2026 16:54
@marc0olo
marc0olo requested review from a team as code owners June 11, 2026 16:54
marc0olo and others added 5 commits June 11, 2026 19:03
Fixed sleep of 20s fails on loaded machines where each PocketIC block
takes 150-200ms (120 blocks × 200ms = 24s exceeds the sleep). Poll every
3s up to 60s and report how long aggregation actually took.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PocketIC simulates a 13-node subnet. It distributes stats with integer
division (num_calls /= 13) before aggregation. With fewer than 13 calls,
every node reports 0 and stats are always 0 regardless of wait time.

Also: print final result on failure for easier debugging.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
set_epoch_from_height is only called during query execution (query_context.rs).
Sleeping without making queries means epoch transitions never trigger a stats
flush to the channel. Fix: poll every 3s with 13 --query calls per round so
stats are flushed when an epoch boundary is crossed during the loop.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@raymondk
raymondk merged commit 061bea9 into master Jun 11, 2026
6 checks passed
@raymondk
raymondk deleted the chore/migrate-query-stats-to-icp-cli branch June 11, 2026 19:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants