Skip to content

Latest commit

 

History

History
73 lines (55 loc) · 4.8 KB

File metadata and controls

73 lines (55 loc) · 4.8 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

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.

Build & Development Commands

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 check

The web server listens on port 3000. Prometheus metrics (if enabled) default to port 9464.

Architecture

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); resolves script_path to inline content at startup
  • src/app_state.rs — Shared state: RwLock<HashMap<String, Vec<MonitorResult>>> storing last 100 results per monitor
  • src/monitor/ — Core monitoring logic:
    • model.rs — Monitor, Step, Expectation, MonitorResult, StepResult types
    • schedule.rs — Scheduling loop, spawns tokio tasks per monitor with initial_delay + interval
    • monitor_logic.rsMonitorable trait, step execution, variable substitution orchestration
    • http.rs — HTTP calls via lazy-static reqwest::Client, OTel trace context propagation
    • expectations.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 /metrics on 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 chars
  • src/otel/ — OpenTelemetry setup: metrics (OTLP/stdout/Prometheus) and tracing (OTLP/stdout)
  • src/scripting/ — Rhai-based scripting engine for scripted monitors:
    • mod.rsScriptRunner: compile-once AST, timeout-wrapped async execute() returning MonitorResult
    • engine.rscreate_engine() with resource limits (1M ops, 64 call levels, 1MB strings, 10K collections)
    • types.rsScriptContext, ScriptResponse, ScriptError
    • host_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 types
  • src/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."

Testing Patterns

  • Unit tests are co-located in modules (#[cfg(test)] blocks)
  • wiremock for HTTP server mocking in tests
  • test_utils.rs provides builder helpers: get_simple_monitor(), get_default_schedule(), etc.
  • Integration tests co-located in src/web_server/api_v1/handlers.rs (#[cfg(test)] module)

Configuration

Config file is YAML (prodzilla.yml by default). Key structure:

  • Monitors define url + http_method (single-step), OR steps array (multi-step), OR script/script_path (scripted) — exactly one type required
  • script_path (YAML-only) is resolved to inline script content at startup; the API only accepts inline script
  • 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

CI

  • test.yamlcargo build && cargo test on 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