DEV Community

Vigilmon
Vigilmon

Posted on

How to Monitor Your Rust (Actix-web) Application with Vigilmon

How to Monitor Your Rust (Actix-web) Application with Vigilmon

Rust applications built with Actix-web are known for exceptional performance and reliability — but even zero-cost abstractions can't protect you from network outages, DNS failures, or upstream service disruptions. External uptime monitoring fills that gap.

This guide shows how to add health checks to your Actix-web app and connect them to Vigilmon for 24/7 external uptime monitoring with instant alerts.

Why External Monitoring for Rust/Actix-web?

Actix-web is blazing fast and memory-safe, but your app still depends on:

  • Network connectivity and DNS resolution
  • Downstream services (PostgreSQL, Redis, external APIs)
  • Docker/systemd process management
  • Cloud infrastructure (load balancers, ingress controllers)

Internal logging and metrics won't tell you when the entire process crashes or the network drops. External monitoring pings your app from outside and alerts you within seconds.

Step 1: Add a Health Check Endpoint

Add a /health route that checks your critical dependencies:

use actix_web::{web, App, HttpServer, HttpResponse, middleware};
use sqlx::PgPool;

async fn health_check(pool: web::Data<PgPool>) -> HttpResponse {
    // Check database connectivity
    match sqlx::query("SELECT 1")
        .fetch_one(pool.get_ref())
        .await
    {
        Ok(_) => HttpResponse::Ok().json(serde_json::json!({
            "status": "healthy",
            "database": "connected",
            "version": env!("CARGO_PKG_VERSION")
        })),
        Err(e) => HttpResponse::ServiceUnavailable().json(serde_json::json!({
            "status": "unhealthy",
            "database": "disconnected",
            "error": e.to_string()
        }))
    }
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let pool = PgPool::connect(&std::env::var("DATABASE_URL").unwrap())
        .await
        .expect("Failed to connect to database");

    let pool_data = web::Data::new(pool);

    HttpServer::new(move || {
        App::new()
            .app_data(pool_data.clone())
            .route("/health", web::get().to(health_check))
            // ... your other routes
    })
    .bind(("0.0.0.0", 8080))?
    .run()
    .await
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Lightweight Liveness vs Readiness Checks

Follow the Kubernetes pattern — separate checks for different purposes:

// Liveness: Is the process alive? (no dependencies)
async fn liveness() -> HttpResponse {
    HttpResponse::Ok().json(serde_json::json!({"status": "alive"}))
}

// Readiness: Can we serve traffic? (check dependencies)
async fn readiness(
    pool: web::Data<PgPool>,
    redis: web::Data<redis::Client>,
) -> HttpResponse {
    let db_ok = sqlx::query("SELECT 1")
        .fetch_one(pool.get_ref())
        .await
        .is_ok();

    let redis_ok = redis
        .get_async_connection()
        .await
        .map(|_| true)
        .unwrap_or(false);

    if db_ok && redis_ok {
        HttpResponse::Ok().json(serde_json::json!({
            "status": "ready",
            "database": true,
            "cache": true
        }))
    } else {
        HttpResponse::ServiceUnavailable().json(serde_json::json!({
            "status": "not_ready",
            "database": db_ok,
            "cache": redis_ok
        }))
    }
}
Enter fullscreen mode Exit fullscreen mode

Register both in your Actix app:

App::new()
    .route("/health/live", web::get().to(liveness))
    .route("/health/ready", web::get().to(readiness))
Enter fullscreen mode Exit fullscreen mode

Step 3: Connect Vigilmon

  1. Sign up at vigilmon.online
  2. Create a new monitor → HTTP Monitor
  3. Set the URL to https://yourdomain.com/health
  4. Check interval: 1 minute (recommended)
  5. Configure alerts: email, Slack, PagerDuty, or webhook
  6. Save and watch your first ping succeed

Vigilmon sends an HTTP GET to your endpoint every minute from multiple regions. If it gets a non-2xx response or no response within the timeout, you're alerted immediately.

Step 4: Actix-web Middleware for Request Timing

Add structured logging with response times so you can correlate Vigilmon alerts with your own logs:

use actix_web::middleware::Logger;
use env_logger::Env;

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    env_logger::init_from_env(Env::default().default_filter_or("info"));

    HttpServer::new(|| {
        App::new()
            .wrap(Logger::new("%a %r %s %b %T")) // includes response time
            .route("/health", web::get().to(health_check))
    })
    .bind(("0.0.0.0", 8080))?
    .run()
    .await
}
Enter fullscreen mode Exit fullscreen mode

When Vigilmon triggers an alert, you can immediately grep your logs for the timestamp to see what happened.

Step 5: Docker Health Checks

If you're running in Docker, add a native health check to your Dockerfile:

FROM rust:1.75 as builder
WORKDIR /app
COPY . .
RUN cargo build --release

FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/myapp /usr/local/bin/myapp

HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \n    CMD curl -f http://localhost:8080/health || exit 1

EXPOSE 8080
CMD ["myapp"]
Enter fullscreen mode Exit fullscreen mode

Docker's built-in health check restarts unhealthy containers. Vigilmon's external monitoring alerts you when the entire host or network is unreachable — something Docker can't detect from inside.

What Vigilmon Monitors That You Can't See Internally

Failure Mode Internal Logs Vigilmon
Process crash Silent ✅ Alert within 1 min
DNS failure Silent ✅ Alert within 1 min
Network partition Silent ✅ Alert within 1 min
SSL certificate expiry Manual check ✅ 30/14/7 day warnings
Slow responses (> 5s) Visible ✅ Alert + timing history
Database connection pool exhaustion Sometimes ✅ Via health endpoint

Free Tier

Vigilmon's free tier includes:

  • 5 monitors
  • 1-minute check intervals
  • Email alerts
  • 90-day uptime history

Perfect for side projects and startups. No credit card required.

Summary

  1. Add /health (and optionally /health/live + /health/ready) to your Actix-web app
  2. Return 200 OK when healthy, 503 when degraded
  3. Connect Vigilmon and set your alert channels
  4. Sleep soundly knowing you'll be the first to know about downtime

Rust gives you memory safety and performance. Vigilmon gives you visibility. Together, your production app is both fast and observable.


Start monitoring free at vigilmon.online — no credit card required.

Top comments (0)