Dioxus is a cross-platform GUI framework built in Rust — the same React-like component model across web (WASM), desktop, and mobile targets. Whether you're shipping a Dioxus fullstack web app or a desktop application with a backend API, failures happen when you least expect them. Vigilmon gives you continuous HTTP monitoring, heartbeat checks, and instant alerts so you catch outages the moment they start.
What You'll Build
- A
/healthendpoint in your Dioxus backend (Axum or Actix-web) - Vigilmon HTTP monitors for your app and health API
- A heartbeat for scheduled background tasks
- Alert channels (email and Slack)
- An uptime badge embedded in your Dioxus web frontend
Prerequisites
- A Dioxus project with a Rust backend (fullstack or separate API server)
- A free Vigilmon account
Step 1: Add a Health Endpoint
For Dioxus fullstack apps using the built-in Axum server, add a health route alongside your app handler:
// src/main.rs (Dioxus fullstack with Axum)
use axum::{routing::get, Json, Router};
use serde_json::{json, Value};
use std::net::SocketAddr;
#[derive(serde::Serialize)]
struct HealthResponse {
status: String,
timestamp: String,
checks: std::collections::HashMap<String, String>,
}
async fn health_handler() -> (axum::http::StatusCode, Json<Value>) {
let mut checks = std::collections::HashMap::new();
let mut degraded = false;
// Database connectivity check
match check_database().await {
Ok(_) => {
checks.insert("database".to_string(), "ok".to_string());
}
Err(e) => {
checks.insert("database".to_string(), format!("error: {}", e));
degraded = true;
}
}
// External service check
match check_external_service().await {
Ok(_) => {
checks.insert("external_api".to_string(), "ok".to_string());
}
Err(e) => {
checks.insert("external_api".to_string(), format!("unreachable: {}", e));
degraded = true;
}
}
let status_code = if degraded {
axum::http::StatusCode::SERVICE_UNAVAILABLE
} else {
axum::http::StatusCode::OK
};
let body = json!({
"status": if degraded { "degraded" } else { "ok" },
"timestamp": chrono::Utc::now().to_rfc3339(),
"checks": checks,
});
(status_code, Json(body))
}
async fn check_database() -> Result<(), Box<dyn std::error::Error>> {
// Replace with your actual database pool check
// pool.acquire().await?;
Ok(())
}
async fn check_external_service() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
client
.get("https://api.yourservice.com/ping")
.timeout(std::time::Duration::from_secs(3))
.send()
.await?;
Ok(())
}
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/health", get(health_handler))
// Mount your Dioxus fullstack app on remaining routes
.fallback(dioxus_axum::render_handler);
let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();
}
Add the required dependencies to Cargo.toml:
[dependencies]
axum = "0.7"
tokio = { version = "1", features = ["full"] }
serde_json = "1"
chrono = { version = "0.4", features = ["serde"] }
reqwest = { version = "0.12", features = ["json"] }
serde = { version = "1", features = ["derive"] }
Test the endpoint:
curl http://localhost:3000/health | jq .
# {"status":"ok","timestamp":"2026-06-29T...","checks":{"database":"ok","external_api":"ok"}}
Step 2: Configure Vigilmon HTTP Monitors
Log in to Vigilmon → Monitors → New Monitor:
Monitor 1: Dioxus Web App
| Field | Value |
|---|---|
| URL | https://yourapp.com/ |
| Method | GET |
| Expected status | 200 |
| Expected body | A stable string from your rendered HTML |
| Check interval | 1 minute |
Monitor 2: Health API
| Field | Value |
|---|---|
| URL | https://yourapp.com/health |
| Method | GET |
| Expected status | 200 |
| Expected body | "status":"ok" |
| Check interval | 1 minute |
Two monitors give you independent visibility: a WASM build serving issue is distinct from a backend database failure.
Step 3: Heartbeat for Background Tasks
Dioxus apps often have server-side background workers. A Vigilmon heartbeat detects silent job crashes:
// src/background.rs
use std::time::Duration;
use tokio::time;
pub async fn start_background_scheduler() {
let heartbeat_url = std::env::var("VIGILMON_HEARTBEAT_URL").unwrap_or_default();
let mut interval = time::interval(Duration::from_secs(10 * 60)); // every 10 minutes
loop {
interval.tick().await;
match run_scheduled_task().await {
Ok(_) => {
if !heartbeat_url.is_empty() {
ping_heartbeat(&heartbeat_url).await;
}
}
Err(e) => {
tracing::error!("Scheduled task failed: {}", e);
// No ping → Vigilmon alerts when the grace window expires
}
}
}
}
async fn run_scheduled_task() -> Result<(), Box<dyn std::error::Error>> {
// Your actual background work
tracing::info!("Running scheduled data sync...");
Ok(())
}
async fn ping_heartbeat(url: &str) {
let client = reqwest::Client::new();
if let Err(e) = client
.get(url)
.timeout(Duration::from_secs(5))
.send()
.await
{
tracing::warn!("Heartbeat ping failed: {}", e);
// Never propagate — monitoring must not crash the job
}
}
Spawn it from main:
tokio::spawn(background::start_background_scheduler());
Set up the heartbeat monitor in Vigilmon:
- Monitors → New Heartbeat Monitor
- Set Expected interval to 20 minutes
- Add to your
.env:
VIGILMON_HEARTBEAT_URL=https://vigilmon.online/api/heartbeat/xxxxxxxx
Step 4: Embed an Uptime Badge in Your Dioxus Web UI
In a Dioxus web component, render the badge as a standard HTML image element:
// src/components/status_badge.rs
use dioxus::prelude::*;
const BADGE_URL: &str = "https://vigilmon.online/api/badge/your-monitor-id.svg";
const STATUS_URL: &str = "https://vigilmon.online/status/your-monitor-slug";
#[component]
pub fn StatusBadge() -> Element {
rsx! {
a {
href: "{STATUS_URL}",
target: "_blank",
rel: "noopener noreferrer",
"aria-label": "Service uptime status",
img {
src: "{BADGE_URL}",
alt: "Uptime",
width: "120",
height: "20",
}
}
}
}
Add it to your app footer:
// src/app.rs
use dioxus::prelude::*;
use crate::components::status_badge::StatusBadge;
#[component]
pub fn App() -> Element {
rsx! {
div {
main { /* your routes */ }
footer {
class: "footer",
StatusBadge {}
}
}
}
}
Step 5: Set Up Alert Channels
In Vigilmon's Alert Channels settings:
- Alert Channels → Email → add your on-call address
- Attach to both HTTP monitors and the heartbeat
Slack
- Create a Slack Incoming Webhook for
#alerts - Alert Channels → Webhook → paste the URL
- Payload template:
{
"text": "🚨 *{{ monitor.name }}* is DOWN\n{{ monitor.url }}\nStatus: {{ event.status }}\n<https://vigilmon.online|Open Vigilmon>"
}
Step 6: Verify Everything Works
# 1. Health endpoint check
curl -s https://yourapp.com/health | jq .status
# 2. Simulate failure — disable DB connection in env and redeploy
# Expected: health returns 503; Vigilmon alert fires within ~2 minutes
# 3. Comment out the heartbeat ping and let the scheduler tick once
# Expected: heartbeat alert fires after the expected interval lapses
# 4. Vigilmon → "Test Alert" → confirm Slack and email delivery
Summary
| Monitor | What It Catches | |---|---| | HTTP app check | WASM serving failures, CDN/reverse proxy issues | | HTTP health API | Database, external API, and service dependency failures | | Heartbeat | Silent background task crashes |
Next Steps
- Create separate Vigilmon workspaces for each deployment target (web, staging, production)
- Use Vigilmon's response time graphs to spot latency spikes from heavy Rust computation or database queries
- Configure multi-channel alerting with escalation rules: email for recoveries, Slack for active outages
Ready to get started? Sign up for Vigilmon free — have your first monitor running in under 5 minutes.