This repo is an Artillery-based load testing suite to measure limits and identify bottlenecks in DataHaven and StorageHub.
- Node.js >= 22 (SDK
@storagehub-sdk/[email protected]declares this) pnpm
pnpm installRequired:
NETWORK(testnet,stagenetorlocal)
Optional:
- none (health checks are unauthenticated)
Network URLs/IDs are intentionally hardcoded in src/networks.ts and are copied from datahaven-monitor:
- Testnet: MSP
https://deo-dh-backend.testnet.datahaven-infra.network - Stagenet: MSP
https://deo-dh-backend.stagenet.datahaven-infra.network - Local: MSP
http://127.0.0.1:8080, RPChttp://127.0.0.1:9888
Local notes:
NETWORK=localmatches the “normal” local StorageHub defaults when you boot a local network from the StorageHub repo with:pnpm docker:start:solochain-evm:initialised- See StorageHub docs: Spawning solochain-evm-initialised fullnet
- It assumes:
- MSP at
http://127.0.0.1:8080 - EVM/Substrate RPC at
http://127.0.0.1:9888/ws://127.0.0.1:9888
- MSP at
- SIWE domain/uri: these should be provided by the dApp doing SIWE (they are not “network” properties). For local testing, a dApp often runs on
localhost:3000orlocalhost:3001.localhost:3001/http://localhost:3001is what the StorageHub repo’sdemo-app(SDK examples) commonly uses.
pnpm fmt— check formattingpnpm fmt:fix— apply formattingpnpm lint— check lint rulespnpm lint:fix— apply safe lint fixespnpm test— build -> preflight -> artillerypnpm test:msp-unauth— standalone unauth MSP load test (no SIWE, no keys)pnpm test:download— file download load test (requires SIWE auth + FILE_KEY)
Examples (local):
NETWORK=local pnpm test:msp-unauthNETWORK=local STORAGEHUB_PRIVATE_KEY=0x... pnpm testLogging is handled by Pino.
Env vars:
LOG_LEVEL:fatal|error|warn|info|debug|trace|silent(default:error)LOG_CONSOLE:true|false(default:true)LOG_FILE_ENABLED:true|false(default:true). When enabled andLOG_FILEis not set, logs are written to./logs/run-<date_time>-pid<PID>.jsonl.LOG_FILE: path to a log file (optional). When set, logs are appended to that file in addition to console (unlessLOG_CONSOLE=false).
Examples:
LOG_LEVEL=debug NETWORK=testnet pnpm testLOG_LEVEL=info LOG_FILE=./artillery.log NETWORK=testnet pnpm testThis test randomly calls:
GET /health(client.info.getHealth())GET /info(client.info.getInfo())
It uses NETWORK=testnet|stagenet and the MSP base URL from src/networks.ts.
Run:
NETWORK=stagenet pnpm test:msp-unauthKnobs (optional):
ARTILLERY_WORKERS=4(true parallel local processes; spawns N concurrent Artillery runs)VU_SLEEP_MIN_MS=50/VU_SLEEP_MAX_MS=250(jitter per request loop)MSP_TIMEOUT_MS=60000(override HTTP timeout)
Metrics emitted (counters + histograms):
msp.health.ok,msp.health.msmsp.info.ok,msp.info.msmsp.req.err(total request errors)
This test authenticates via SIWE and downloads a file from the MSP, measuring throughput and latency.
Required env vars:
NETWORK(testnetorstagenet)FILE_KEY(the file key/hash to download)
Run:
NETWORK=stagenet FILE_KEY=<your-file-key> pnpm test:downloadKnobs (optional):
ARTILLERY_WORKERS=4(parallel local processes)LOG_LEVEL=info(see Logging section)
Metrics emitted:
download.siwe.ok,download.siwe.ms(SIWE auth)download.file.ok,download.file.ms(file download)download.bytes(total bytes downloaded per request)download.siwe.err,download.file.err(error counters)
This test expects a per-VU privateKey variable from config.payload in scenarios/artillery.yml.
- Create
data/private_keys.csv(ignored by git), based on the example:
data/private_keys.example.csv
Notes:
pnpm preflightwill useSTORAGEHUB_PRIVATE_KEYif set, otherwise it will use the first key indata/private_keys.csv.- If Artillery does not inject
privateKeyintocontext.vars(depends on engine/runtime), the scenario will fall back to reading keys directly fromdata/private_keys.csv(round-robin).
- Run:
NETWORK=stagenet LOG_LEVEL=info pnpm testCounters:
sdk.storagehub.connect.oksdk.msp.connect.oksdk.disconnect.oksdk.connect.error
Timings:
sdk.storagehub.connect.mssdk.msp.connect.ms