tutorial

Monitoring Hurl-Tested HTTP Services with Vigilmon: External Uptime, Health Checks & Heartbeat Monitoring

Practical guide to complementing Hurl's command-line HTTP test assertions with Vigilmon's external uptime checks — health endpoints, synthetic HTTP monitors, heartbeat monitors for scheduled Hurl test runs, and independent alerting for your APIs.

Hurl is a command-line tool for running HTTP requests defined in plain-text .hurl files. It supports chained requests, response assertions, JSON path checks, and XPath queries — making it a compact integration testing layer for APIs and web services. Hurl catches regressions inside your CI pipeline, but it can only run when someone or something triggers it. When your service is live in production, nothing automatically retries a Hurl file every 60 seconds from multiple geographic locations. Vigilmon does. It sits outside your infrastructure, probes your endpoints continuously from independent vantage points, and alerts your team the moment availability degrades — independent of whether your CI pipeline is healthy.

This tutorial covers adding external uptime monitoring to services validated by Hurl, and monitoring your Hurl test jobs themselves.

What You'll Build

  • A /health endpoint in your HTTP service that Hurl already tests
  • A Vigilmon HTTP monitor with JSON body assertions mirroring Hurl's response checks
  • A heartbeat monitor that detects when your scheduled Hurl regression suite stops running
  • Alert routing that keeps CI test failures and production uptime alerts distinct

Prerequisites

  • A service with HTTP endpoints tested by one or more .hurl files
  • A publicly reachable HTTPS endpoint for the service
  • A free account at vigilmon.online

Step 1: Add a Health Endpoint That Mirrors Your Hurl Assertions

Hurl asserts response content, status codes, and headers. Build a /health endpoint that exercises the same runtime dependencies your Hurl files probe so Vigilmon's external checks reflect the same system state.

Node.js / Express

// src/health.js
import os from 'os';

export function registerHealthRoute(app, db, cache) {
  app.get('/health', async (req, res) => {
    const checks = {};
    let ok = true;

    try {
      await db.raw('SELECT 1');
      checks.database = 'ok';
    } catch (err) {
      checks.database = `error: ${err.message}`;
      ok = false;
    }

    try {
      await cache.ping();
      checks.cache = 'ok';
    } catch (err) {
      checks.cache = `error: ${err.message}`;
      ok = false;
    }

    res.status(ok ? 200 : 503).json({
      status: ok ? 'ok' : 'degraded',
      checks,
      host: os.hostname(),
    });
  });
}

Python (FastAPI)

# app/health.py
import os
import redis
import asyncpg
from fastapi import FastAPI
from fastapi.responses import JSONResponse

app = FastAPI()

@app.get("/health")
async def health():
    checks = {}
    ok = True

    try:
        conn = await asyncpg.connect(os.environ["DATABASE_URL"], timeout=3)
        await conn.fetchval("SELECT 1")
        await conn.close()
        checks["database"] = "ok"
    except Exception as exc:
        checks["database"] = f"error: {exc}"
        ok = False

    try:
        r = redis.from_url(os.environ["REDIS_URL"], socket_timeout=3)
        r.ping()
        checks["cache"] = "ok"
    except Exception as exc:
        checks["cache"] = f"error: {exc}"
        ok = False

    return JSONResponse(
        status_code=200 if ok else 503,
        content={"status": "ok" if ok else "degraded", "checks": checks},
    )

Corresponding Hurl assertion (for reference)

# tests/health.hurl
GET https://api.example.com/health

HTTP 200
[Asserts]
jsonpath "$.status" == "ok"
jsonpath "$.checks.database" == "ok"
jsonpath "$.checks.cache" == "ok"

Verify the endpoint before configuring Vigilmon:

hurl --test tests/health.hurl
# tests/health.hurl: Success (1 request(s) in 42 ms)

Step 2: Configure Vigilmon HTTP Monitor

  1. Log in to VigilmonAdd Monitor → HTTP.
  2. URL: https://api.example.com/health
  3. Check interval: 60 seconds.
  4. Response timeout: 10 seconds.
  5. Expected status code: 200.
  6. JSON body assertion:
    • Path: status
    • Expected value: ok
  7. Click Save.

Vigilmon probes from multiple external locations concurrently and requires a quorum of probe agents to agree on a failure before firing an alert. This eliminates false positives from transient regional routing issues — the same false positives that occasionally cause Hurl runs in a remote CI environment to flake.

Monitor per major endpoint

Each critical endpoint your Hurl files test should have its own Vigilmon monitor:

| Endpoint | Hurl file | Vigilmon interval | |---|---|---| | GET /health | tests/health.hurl | 60 s | | GET /api/v1/users | tests/users.hurl | 60 s | | POST /api/v1/orders | tests/orders.hurl | 120 s | | GET /metrics | tests/metrics.hurl | 120 s |

Group monitors under a Monitor group named after the service or environment.


Step 3: Heartbeat Monitor for Scheduled Hurl Test Runs

Hurl excels at regression suites run on a schedule — nightly smoke tests, hourly API contract checks, or pre-deploy validations. If those scheduled runs silently stop executing because a cron job drifts or a runner goes offline, you want to know immediately. Vigilmon heartbeat monitors detect exactly this failure mode.

Add a heartbeat ping at the end of each scheduled Hurl invocation:

#!/bin/bash
# scripts/run-hurl-suite.sh
set -euo pipefail

echo "Running Hurl regression suite..."

hurl --test \
  --variable HOST=https://api.example.com \
  --report-html reports/ \
  tests/*.hurl

echo "All tests passed — sending heartbeat"
curl -s -X POST "${VIGILMON_HEARTBEAT_URL}" --max-time 5

In Vigilmon, create a Heartbeat monitor with a grace period 30 minutes longer than your scheduled run interval. If the run is hourly, set the grace period to 90 minutes.

GitHub Actions integration

# .github/workflows/nightly-hurl-suite.yml
name: Nightly Hurl Regression Suite

on:
  schedule:
    - cron: '0 1 * * *'  # 1 AM UTC daily

jobs:
  hurl-suite:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Hurl
        run: |
          VERSION=4.2.0
          curl -LO "https://github.com/Orange-OpenSource/hurl/releases/download/${VERSION}/hurl_${VERSION}_amd64.deb"
          sudo dpkg -i "hurl_${VERSION}_amd64.deb"

      - name: Run Hurl test suite
        env:
          HOST: ${{ vars.API_HOST }}
        run: hurl --test --variable HOST=$HOST tests/*.hurl

      - name: Send Vigilmon heartbeat
        if: success()
        run: curl -X POST "${{ secrets.VIGILMON_HEARTBEAT_URL }}"

Step 4: TLS Certificate Monitoring

Hurl validates TLS by default — it will fail if your certificate is expired or invalid during a run. But Hurl runs on a schedule, not continuously. Vigilmon's TLS monitor checks certificate expiry continuously and alerts you days before expiry so you can renew before Hurl starts failing.

In Vigilmon → Add Monitor → SSL/TLS certificate:

  • Host: api.example.com
  • Alert before expiry: 30 days

No code changes are needed. Vigilmon reads the certificate directly from the TLS handshake.


Step 5: Alert Routing Strategy

Hurl fires alerts in your CI pipeline: test failures show up as build failures in GitHub Actions, GitLab CI, or your CI tool of choice. Vigilmon fires alerts for production availability: endpoint down, heartbeat missed, certificate expiring. These are complementary and should route to different channels.

| Failure mode | Source | Route to | |---|---|---| | Hurl assertion failed in CI | CI pipeline | Slack #api-ci-failures + PR status | | Production endpoint down | Vigilmon | PagerDuty + Slack #prod-alerts | | Nightly Hurl suite missed | Vigilmon | Slack #api-ops-critical | | TLS certificate expiring | Vigilmon | DevOps team + calendar reminder |

Configure Vigilmon alert channels under Alerts → Add channel:

  • Email: on-call distribution list.
  • PagerDuty webhook: primary on-call rotation for production outages.
  • Slack webhook: a #vigilmon-alerts channel for visibility.

Step 6: Public Status Page

Hurl test results live in your CI system, visible only to your team. Your API consumers don't have access to CI dashboards and shouldn't need to reach out to ask if an outage is planned. Vigilmon's public status page gives them a transparent availability view.

  1. In Vigilmon → Status Pages → Create.
  2. Add your production API monitors and nightly suite heartbeat monitor.
  3. Configure a custom domain (status.example.com) or use the Vigilmon subdomain.
  4. Embed a status badge in your API documentation:
<img src="https://vigilmon.online/badge/<monitor-id>.svg" alt="API Status" />

What Vigilmon Adds to a Hurl Workflow

| Capability | Hurl | Vigilmon | |---|---|---| | Response assertion by JSON path | Yes | Yes (JSON body check) | | Chained multi-step request flows | Yes | No | | Plain-text test file format | Yes | No | | CI pipeline integration | Yes | No | | Continuous 24/7 external probing | No | Yes | | Multi-location quorum-based checks | No | Yes | | TLS/SSL certificate expiry alerts | No | Yes | | Scheduled job heartbeat monitoring | No | Yes | | Public status page | No | Yes | | Independent of CI/CD pipeline health | No | Yes |


Hurl gives you precise, readable HTTP assertions inside your CI pipeline. Vigilmon gives you the continuous, external perspective that catches production failures between CI runs. Together they cover both the regression-testing and the live-service-monitoring sides of API reliability.

Add external uptime monitoring to your Hurl-tested services today — register free at vigilmon.online.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →