DEV Community

Vigilmon
Vigilmon

Posted on

How to Monitor Your Fresh (Deno) Application with Vigilmon

How to Monitor Your Fresh (Deno) Application with Vigilmon

Fresh is Deno's full-stack web framework — built for the edge, with islands architecture, zero JS by default, and server-side rendering. This guide shows how to add health monitoring to your Fresh app and hook it up to Vigilmon for external uptime checks.

Adding a Health Route to Fresh

Fresh uses file-based routing. Create a health endpoint in your routes/ directory:

Basic Health Endpoint

// routes/health.ts
import { FreshContext, Handlers } from '$fresh/server.ts';

export const handler: Handlers = {
  GET(_req: Request, _ctx: FreshContext) {
    const health = {
      status: 'ok',
      framework: 'fresh',
      runtime: 'deno',
      version: Deno.version.deno,
      timestamp: new Date().toISOString(),
    };

    return new Response(JSON.stringify(health), {
      status: 200,
      headers: {
        'Content-Type': 'application/json',
        'Cache-Control': 'no-cache, no-store',
      },
    });
  },
};
Enter fullscreen mode Exit fullscreen mode

Health Check with KV Database

Fresh apps often use Deno KV. Include a connectivity check:

// routes/health.ts
import { FreshContext, Handlers } from '$fresh/server.ts';

export const handler: Handlers = {
  async GET(_req: Request, _ctx: FreshContext) {
    let kvStatus = 'unknown';

    try {
      const kv = await Deno.openKv();
      await kv.get(['health_check']);
      kvStatus = 'connected';
      kv.close();
    } catch (_err) {
      kvStatus = 'error';
    }

    const isHealthy = kvStatus === 'connected';

    return new Response(
      JSON.stringify({
        status: isHealthy ? 'ok' : 'degraded',
        kv: kvStatus,
        timestamp: new Date().toISOString(),
      }),
      {
        status: isHealthy ? 200 : 503,
        headers: { 'Content-Type': 'application/json' },
      }
    );
  },
};
Enter fullscreen mode Exit fullscreen mode

Deep Health Check (API Route)

// routes/api/health.ts
import { FreshContext, Handlers } from '$fresh/server.ts';

interface HealthCheck {
  name: string;
  status: 'pass' | 'fail';
  latencyMs?: number;
}

export const handler: Handlers = {
  async GET(_req: Request, _ctx: FreshContext) {
    const startTime = Date.now();
    const checks: HealthCheck[] = [];

    // Check 1: KV store
    try {
      const kvStart = Date.now();
      const kv = await Deno.openKv();
      await kv.get(['ping']);
      kv.close();
      checks.push({ name: 'kv', status: 'pass', latencyMs: Date.now() - kvStart });
    } catch {
      checks.push({ name: 'kv', status: 'fail' });
    }

    // Check 2: External API (if you depend on one)
    // try {
    //   const apiStart = Date.now();
    //   const res = await fetch('https://api.your-service.com/ping');
    //   checks.push({ name: 'external-api', status: res.ok ? 'pass' : 'fail', latencyMs: Date.now() - apiStart });
    // } catch {
    //   checks.push({ name: 'external-api', status: 'fail' });
    // }

    const allPassing = checks.every(c => c.status === 'pass');

    return new Response(
      JSON.stringify({
        status: allPassing ? 'ok' : 'degraded',
        checks,
        totalLatencyMs: Date.now() - startTime,
        timestamp: new Date().toISOString(),
      }),
      {
        status: allPassing ? 200 : 503,
        headers: { 'Content-Type': 'application/json' },
      }
    );
  },
};
Enter fullscreen mode Exit fullscreen mode

Heartbeat for Fresh Background Tasks

If you're using Deno.cron in your Fresh app:

// utils/cron.ts
const HEARTBEAT = 'https://vigilmon.online/api/heartbeat/YOUR_MONITOR_ID';

Deno.cron('Cleanup', '0 3 * * *', async () => {
  const kv = await Deno.openKv();

  try {
    // Your cleanup logic
    await cleanupExpiredSessions(kv);

    // Send heartbeat on success
    await fetch(HEARTBEAT, { method: 'POST' });
  } catch (err) {
    console.error('Cron job failed:', err);
  } finally {
    kv.close();
  }
});
Enter fullscreen mode Exit fullscreen mode

Deploying Fresh on Deno Deploy

Deno Deploy runs Fresh at the edge. Monitor your deployed app:

  1. Your health endpoint is at: https://your-app.deno.dev/health
  2. Add this URL to Vigilmon
  3. Vigilmon checks from multiple regions

If your Fresh app is on a custom domain:

  • Monitor: https://yourdomain.com/health
  • SSL monitor: https://yourdomain.com

Setting Up Vigilmon for Fresh

  1. Sign up at vigilmon.online
  2. Add HTTP monitorhttps://your-fresh-app.deno.dev/health
  3. Set interval: 1 min or 5 min
  4. Add SSL monitor if on custom domain
  5. Configure alerts: email + Slack

Self-Hosted Fresh (with systemd)

[Unit]
Description=Fresh Deno Application
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/fresh-app
ExecStart=/usr/local/bin/deno run \n  --allow-net \n  --allow-env \n  --allow-read \n  --allow-write \n  main.ts
Restart=always
RestartSec=5

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

Monitoring Checklist for Fresh Apps

  • [ ] routes/health.ts returning 200 with JSON
  • [ ] KV connectivity check in health endpoint
  • [ ] Heartbeat monitors for Deno.cron jobs
  • [ ] Uptime monitor on Vigilmon
  • [ ] SSL certificate monitor
  • [ ] Alert channels configured

Start monitoring your Fresh app free →

Top comments (0)