DEV Community

Vigilmon
Vigilmon

Posted on

How to Monitor Actix-web Applications with Vigilmon (Rust)

How to Monitor Actix-web Applications with Vigilmon (Rust)

Actix-web is one of the fastest web frameworks in the world — a Rust powerhouse that consistently tops TechEmpower benchmarks. But even the fastest framework needs external monitoring. A Rust panic, misconfigured systemd service, or network partition won't show up in your application logs until after users notice. This guide shows you how to monitor Actix-web applications with Vigilmon.

Why Rust/Actix Still Needs External Monitoring

Rust's memory safety guarantees eliminate entire categories of bugs — but not all failure modes:

  • Logic panics can crash the process even in safe Rust
  • External dependency failures (database, Redis, S3) bring down your app
  • Infrastructure issues — VPS crashes, OOM kills, kernel panics
  • Deployment errors — bad binary upload, port conflicts
  • Network partitions — your server is fine but unreachable from the internet

Vigilmon catches all of these.

Step 1: Add a Health Check Route

// src/main.rs
use actix_web::{web, App, HttpServer, HttpResponse, Result};
use serde_json::json;

async fn health_check() -> HttpResponse {
    HttpResponse::Ok().json(json!({
        "status": "ok",
        "service": "my-actix-app"
    }))
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .route("/health", web::get().to(health_check))
            // ... other routes
    })
    .bind("0.0.0.0:8080")?
    .run()
    .await
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Database Health Check with SQLx

use actix_web::{web, HttpResponse};
use sqlx::PgPool;
use serde_json::json;

async fn health_deep(pool: web::Data<PgPool>) -> HttpResponse {
    match sqlx::query("SELECT 1")
        .fetch_one(pool.get_ref())
        .await
    {
        Ok(_) => HttpResponse::Ok().json(json!({
            "status": "ok",
            "database": "connected"
        })),
        Err(e) => HttpResponse::ServiceUnavailable().json(json!({
            "status": "error",
            "database": 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 create pool");

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

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

Step 3: Structured Health Check Response

For a more complete health check:

use actix_web::{web, HttpResponse};
use serde::{Deserialize, Serialize};
use std::time::{SystemTime, UNIX_EPOCH};

#[derive(Serialize)]
struct HealthResponse {
    status: String,
    timestamp: u64,
    version: String,
}

async fn health() -> HttpResponse {
    let timestamp = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_secs();

    HttpResponse::Ok().json(HealthResponse {
        status: "ok".to_string(),
        timestamp,
        version: env!("CARGO_PKG_VERSION").to_string(),
    })
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Configure Vigilmon

  1. Sign up at vigilmon.online (free)
  2. Click Add Monitor
  3. URL: https://yourapp.example.com/health
  4. Check interval: 1 minute
  5. Expected status: 200
  6. Alert after: 2 consecutive failures

Step 5: Running Actix-web in Production

Typical Actix-web production setup uses systemd:

# /etc/systemd/system/myapp.service
[Unit]
Description=My Actix-web Application
After=network.target

[Service]
Type=simple
User=myapp
Environment=DATABASE_URL=postgresql://user:pass@localhost/mydb
Environment=RUST_LOG=info
ExecStart=/usr/local/bin/myapp
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode

Restart=on-failure means systemd will restart your app — but Vigilmon tells you how long the outage was and when it happened.

Step 6: Behind nginx with TLS

server {
    listen 443 ssl http2;
    server_name api.example.com;

    location /health {
        proxy_pass http://127.0.0.1:8080/health;
        proxy_read_timeout 5s;
    }

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection keep-alive;
    }
}
Enter fullscreen mode Exit fullscreen mode

Monitor the HTTPS URL — this tests the full stack including nginx and TLS.

Step 7: Docker Health Check

FROM debian:bookworm-slim
COPY --from=builder /app/target/release/myapp /usr/local/bin/myapp

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

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

Step 8: Actix-web with Tokio Runtime

For high-traffic Actix-web apps, configure multiple worker threads:

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .route("/health", web::get().to(health))
    })
    .workers(num_cpus::get())  // One worker per CPU core
    .bind("0.0.0.0:8080")?
    .run()
    .await
}
Enter fullscreen mode Exit fullscreen mode

Vigilmon will hit any available worker — even if one is stuck, others respond.

Monitor Setup for Actix-web

Monitor Endpoint Interval Alert
Basic health /health 1 min 2 failures
DB health /health/deep 5 min 1 failure
API root / 5 min 2 failures
SSL cert (auto) Daily 30 days

Summary

Actix-web is blazing fast and memory-safe — but production reliability requires external monitoring. Vigilmon's 1-minute check interval from multiple regions means you'll know within 2 minutes of any outage.

Start monitoring your Actix-web app free on Vigilmon.

Top comments (0)