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
}
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
}
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(),
})
}
Step 4: Configure Vigilmon
- Sign up at vigilmon.online (free)
- Click Add Monitor
- URL:
https://yourapp.example.com/health - Check interval: 1 minute
- Expected status: 200
- 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
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;
}
}
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"]
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
}
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.
Top comments (0)