This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Prodzilla is a lightweight synthetic monitoring tool written in Rust that tests user flows in production. It supports three monitor types: single-step monitors (traditional health checks), multi-step monitors (chained requests with variable passing between steps), and scripted monitors (arbitrary Rhai scripts with full HTTP access and assertions). Runs with <15MB RAM. Fully integrated with OpenTelemetry for tracing and metrics.
cargo run # Run with default prodzilla.yml config
cargo run -- -f custom.yml # Run with custom config file
cargo build --locked --release # Release build
cargo test --verbose # Run all tests
cargo clippy --all-targets --all-features # Lint
cargo fmt --all -- --check # Format checkThe web server listens on port 3000. Prometheus metrics (if enabled) default to port 9464.
Single binary, async Rust application using Axum (web) and Tokio (runtime).
Core flow: main.rs → loads YAML config → initializes OTel → spawns per-monitor async scheduling tasks → starts Axum web server.
Key modules:
src/config.rs— YAML config loading with validation (unique monitor names, mutual exclusivity of single-step vs multi-step vs scripted fields); resolvesscript_pathto inline content at startupsrc/app_state.rs— Shared state:RwLock<HashMap<String, Vec<MonitorResult>>>storing last 100 results per monitorsrc/monitor/— Core monitoring logic:model.rs— Monitor, Step, Expectation, MonitorResult, StepResult typesschedule.rs— Scheduling loop, spawns tokio tasks per monitor with initial_delay + intervalmonitor_logic.rs—Monitorabletrait, step execution, variable substitution orchestrationhttp.rs— HTTP calls via lazy-static reqwest::Client, OTel trace context propagationexpectations.rs— Response validation (Equals, NotEquals, Contains, Matches regex, IsOneOf with|separator)variables.rs—${{ steps.name.response.body.field }},${{ generate.uuid }},${{ env.VAR }}substitution via regex
src/web_server/— API routes under/api/v1:GET/POST /monitors,GET /monitors/summary,GET/PUT/DELETE /monitors/:name,GET /monitors/:name/results,POST /monitors/:name/trigger. Prometheus/metricson separate port (default 9464). SPA fallback serves frontend for all other routes.src/alerts/outbound_webhook.rs— Webhook alerting with auto-detected Slack formatting, body truncation to 500 charssrc/otel/— OpenTelemetry setup: metrics (OTLP/stdout/Prometheus) and tracing (OTLP/stdout)src/scripting/— Rhai-based scripting engine for scripted monitors:mod.rs—ScriptRunner: compile-once AST, timeout-wrapped asyncexecute()returningMonitorResultengine.rs—create_engine()with resource limits (1M ops, 64 call levels, 1MB strings, 10K collections)types.rs—ScriptContext,ScriptResponse,ScriptErrorhost_functions/— Rhai-callable functions:http_get/post/put/delete/request,assert,assert_eq,parse_json,to_json,env,uuid,timestamp,log_info/warn/debug,step(name, closure)
src/errors.rs— Custom error typessrc/test_utils.rs— Builder functions for test monitor construction
Terminology: "Monitors" is the unified term (replaces older "probes"/"stories" naming). Each monitor has one or more "steps."
- Unit tests are co-located in modules (
#[cfg(test)]blocks) wiremockfor HTTP server mocking in teststest_utils.rsprovides builder helpers:get_simple_monitor(),get_default_schedule(), etc.- Integration tests co-located in
src/web_server/api_v1/handlers.rs(#[cfg(test)]module)
Config file is YAML (prodzilla.yml by default). Key structure:
- Monitors define
url+http_method(single-step), ORstepsarray (multi-step), ORscript/script_path(scripted) — exactly one type required script_path(YAML-only) is resolved to inlinescriptcontent at startup; the API only accepts inlinescript- Optional
script_timeout_seconds(default 60) controls scripted monitor execution timeout - Variable syntax:
${{ steps.step-name.response.body.fieldName }}for chaining step outputs in multi-step monitors - OTel configured via standard env vars:
OTEL_EXPORTER_OTLP_ENDPOINT,OTEL_METRICS_EXPORTER,OTEL_TRACES_EXPORTER,RUST_LOG
- test.yaml —
cargo build && cargo teston push to main and PRs - lint.yaml — clippy + fmt on all pushes
- release.yaml — GitHub releases on
v[0-9]+.*tags - docker.yaml — Multi-platform Docker images (amd64/arm64) to GHCR on tag push