tutorial

How to Monitor WarpDB Uptime and Health with Vigilmon

WarpDB is a time-series database built around the Geo Time Series language — powerful for IoT and telemetry, but silent failures in its HTTP API or ingestion pipeline can blind your observability stack. Here's how to monitor WarpDB availability with Vigilmon.

WarpDB (also known as Warp 10) is a time-series platform built around the Geo Time Series (GTS) language, designed for high-density sensor data, IoT telemetry, and geospatial analytics. Unlike conventional metrics databases, WarpDB ingest and query paths are tightly coupled to its HTTP API and its custom WarpScript execution engine — meaning a silent failure in any layer can stop data flowing without any obvious error to your application.

Vigilmon gives you external visibility into WarpDB availability through HTTP probe monitoring and heartbeat monitoring for ingestion pipelines. This tutorial walks through both.


Why WarpDB Monitoring Matters

WarpDB's architecture separates ingestion (the /api/v0/update endpoint) from query execution (the /api/v0/exec endpoint). These paths can fail independently:

  • The update endpoint can stop accepting data while queries continue to return stale results — your dashboards look healthy while new sensor data is silently dropped
  • The exec endpoint can time out on complex WarpScript queries without surfacing errors to upstream callers
  • WarpDB's LevelDB or HBase backend can become unavailable while the HTTP layer continues accepting requests, queuing them nowhere
  • Token authentication failures return HTTP 403 but no alarm — ingestion silently stops for the affected data source

Internal process monitoring sees WarpDB running. External monitoring with Vigilmon sees whether your data is actually flowing.


Step 1: Build a WarpDB Health Endpoint

WarpDB exposes a native /api/v0/check endpoint that returns HTTP 200 when the platform is operational. Test it directly:

curl -i https://your-warpdb-host:8080/api/v0/check
# HTTP/1.1 200 OK
# Warp 10 (c) Cityzen Data

For deeper health coverage — verifying both ingestion and query paths — wrap the WarpDB API in a lightweight sidecar health endpoint.

Node.js Sidecar Health Endpoint

// warpdb-health.js — checks both WarpDB ingest and query paths
const express = require('express');
const axios = require('axios');

const app = express();
const WARPDB_URL = process.env.WARPDB_URL || 'http://localhost:8080';
const WRITE_TOKEN = process.env.WARPDB_WRITE_TOKEN;
const READ_TOKEN = process.env.WARPDB_READ_TOKEN;

app.get('/health/warpdb', async (req, res) => {
  const results = {};

  // Check 1: platform liveness
  try {
    await axios.get(`${WARPDB_URL}/api/v0/check`, { timeout: 5000 });
    results.platform = 'ok';
  } catch (err) {
    return res.status(503).json({ status: 'down', check: 'platform', error: err.message });
  }

  // Check 2: ingestion path — write a synthetic GTS point
  try {
    const now = Date.now() * 1000; // WarpDB uses microseconds
    const gtsLine = `${now}// health.probe{source=vigilmon} 1\n`;
    await axios.post(`${WARPDB_URL}/api/v0/update`, gtsLine, {
      headers: { 'X-Warp10-Token': WRITE_TOKEN, 'Content-Type': 'text/plain' },
      timeout: 5000,
    });
    results.ingest = 'ok';
  } catch (err) {
    return res.status(503).json({ status: 'degraded', check: 'ingest', error: err.message });
  }

  // Check 3: query path — fetch the synthetic point back
  try {
    const script = `[ '${READ_TOKEN}' 'health.probe' { 'source' 'vigilmon' } NOW 60000000 ] FETCH`;
    const response = await axios.post(`${WARPDB_URL}/api/v0/exec`, script, {
      headers: { 'Content-Type': 'text/plain' },
      timeout: 10000,
    });
    if (!Array.isArray(response.data) || response.data.length === 0) {
      return res.status(503).json({ status: 'degraded', check: 'query', reason: 'no_data_returned' });
    }
    results.query = 'ok';
  } catch (err) {
    return res.status(503).json({ status: 'degraded', check: 'query', error: err.message });
  }

  return res.status(200).json({ status: 'ok', ...results });
});

app.listen(3001);

Python Equivalent

# warpdb_health.py — FastAPI sidecar for WarpDB health
import os, time
import httpx
from fastapi import FastAPI
from fastapi.responses import JSONResponse

app = FastAPI()
WARPDB_URL = os.environ.get("WARPDB_URL", "http://localhost:8080")
WRITE_TOKEN = os.environ["WARPDB_WRITE_TOKEN"]
READ_TOKEN = os.environ["WARPDB_READ_TOKEN"]

@app.get("/health/warpdb")
async def warpdb_health():
    async with httpx.AsyncClient(timeout=10.0) as client:
        # Platform liveness
        try:
            await client.get(f"{WARPDB_URL}/api/v0/check")
        except Exception as e:
            return JSONResponse(status_code=503, content={"status": "down", "check": "platform", "error": str(e)})

        # Ingestion path
        now_us = int(time.time() * 1_000_000)
        gts_line = f"{now_us}// health.probe{{source=vigilmon}} 1\n"
        try:
            await client.post(
                f"{WARPDB_URL}/api/v0/update",
                content=gts_line,
                headers={"X-Warp10-Token": WRITE_TOKEN, "Content-Type": "text/plain"},
            )
        except Exception as e:
            return JSONResponse(status_code=503, content={"status": "degraded", "check": "ingest", "error": str(e)})

        # Query path
        script = f"[ '{READ_TOKEN}' 'health.probe' {{ 'source' 'vigilmon' }} NOW 60000000 ] FETCH"
        try:
            r = await client.post(
                f"{WARPDB_URL}/api/v0/exec",
                content=script,
                headers={"Content-Type": "text/plain"},
            )
            data = r.json()
            if not isinstance(data, list) or len(data) == 0:
                return JSONResponse(status_code=503, content={"status": "degraded", "check": "query", "reason": "no_data"})
        except Exception as e:
            return JSONResponse(status_code=503, content={"status": "degraded", "check": "query", "error": str(e)})

    return {"status": "ok", "platform": "ok", "ingest": "ok", "query": "ok"}

Deploy and verify:

curl -i https://your-app.example.com/health/warpdb
# HTTP/1.1 200 OK
# {"status":"ok","platform":"ok","ingest":"ok","query":"ok"}

Step 2: Configure a Vigilmon HTTP Monitor for WarpDB

  1. Log in to vigilmon.online and go to Monitors → New Monitor
  2. Choose HTTP / HTTPS
  3. Set the URL to your health endpoint: https://your-app.example.com/health/warpdb
  4. Set the check interval to 1 minute
  5. Under Expected response, configure:
    • Status code: 200
    • Response body contains: "status":"ok"
    • Response time threshold: 5000ms (WarpDB exec can be slow on large datasets)
  6. Under Alert channels, assign your Slack or email channel
  7. Save the monitor

Vigilmon probes from multiple geographic regions. A transient single-region blip will not page you — Vigilmon requires multi-region consensus before opening an incident, so you get confident, actionable alerts rather than noise.

Failure Coverage

| Failure Mode | Process Monitor | Vigilmon | |---|---|---| | WarpDB process crash | ✓ | ✓ | | Ingest endpoint rejects writes | ✗ | ✓ | | WarpScript exec timeout | ✗ | ✓ | | Token authentication failure | ✗ | ✓ | | Backend (LevelDB/HBase) unavailable | ✗ | ✓ |


Step 3: Heartbeat Monitoring for WarpDB Ingestion Pipelines

IoT and telemetry systems that continuously push data to WarpDB — MQTT bridges, Telegraf agents, custom collector processes — will stop silently when WarpDB becomes unavailable. The collector process continues running; data is simply lost. Vigilmon's heartbeat monitors detect this gap.

Set Up the Heartbeat Monitor

  1. In Vigilmon, go to Monitors → New Monitor → Heartbeat
  2. Set the name: warpdb-ingestion-pipeline
  3. Set the expected interval to match your ingestion frequency (e.g., 5 minutes)
  4. Set the grace period: 10 minutes
  5. Save — copy the heartbeat URL, e.g. https://vigilmon.online/heartbeat/abc123xyz

Wire It Into Your Pipeline

Custom Node.js Collector:

const axios = require('axios');
const HEARTBEAT_URL = process.env.VIGILMON_HEARTBEAT_URL;

async function ingestBatch(dataPoints) {
  const gtsLines = dataPoints.map(p =>
    `${p.timestamp * 1000}// ${p.name}{} ${p.value}`
  ).join('\n');

  await axios.post(`${WARPDB_URL}/api/v0/update`, gtsLines, {
    headers: { 'X-Warp10-Token': process.env.WARPDB_WRITE_TOKEN },
  });

  // Ping Vigilmon only after successful ingest
  await axios.get(HEARTBEAT_URL).catch(() => {});
}

Telegraf with exec output:

Add an outputs.exec to your Telegraf config to ping Vigilmon after each successful flush:

[[outputs.exec]]
  command = ["curl", "-s", "https://vigilmon.online/heartbeat/abc123xyz"]
  timeout = "5s"
  use_batch_format = false

Python Collector:

import requests, os

HEARTBEAT_URL = os.environ["VIGILMON_HEARTBEAT_URL"]

def ingest_to_warpdb(data_points):
    lines = "\n".join(
        f"{p['ts'] * 1_000_000}// {p['name']}{{}} {p['value']}"
        for p in data_points
    )
    resp = requests.post(
        f"{WARPDB_URL}/api/v0/update",
        data=lines,
        headers={"X-Warp10-Token": os.environ["WARPDB_WRITE_TOKEN"]},
        timeout=10,
    )
    resp.raise_for_status()
    # Signal successful delivery to Vigilmon
    requests.get(HEARTBEAT_URL, timeout=5)

Step 4: Monitor Multiple WarpDB Instances

Production WarpDB deployments often run multiple Warp 10 nodes behind a load balancer, with separate ingestion and query clusters. Monitor each node independently in Vigilmon:

[warpdb-ingest-1] /health/warpdb
[warpdb-ingest-2] /health/warpdb
[warpdb-query-1]  /health/warpdb
[warpdb-query-2]  /health/warpdb

Group them into a single Vigilmon Status Page so your team has one view of the entire WarpDB tier.

For the native /api/v0/check endpoint on nodes that don't have a sidecar:

  1. Create an HTTP monitor pointing directly to https://warpdb-node:8080/api/v0/check
  2. Set the expected status code to 200
  3. Set the response body contains check to Warp 10

Step 5: Alert Routing for Time-Series Outages

WarpDB outages cascade: ingestion stops → pipelines queue up → downstream dashboards show stale data → on-call engineers are blind to the very system they should use to diagnose other outages.

Configure alert channels in Vigilmon:

  1. Ingestion health monitor → immediate Slack + PagerDuty (P1 — data loss)
  2. Query health monitor → Slack + email (P1 — dashboard blindness)
  3. Ingestion pipeline heartbeats → Slack (P2 — silent pipeline failure)

Set a response time threshold of 5000ms for the exec check — slow WarpScript execution is often a precursor to full query engine saturation.


Summary

WarpDB failures are invisible to your application layer — queries return stale data while new data is silently dropped. Vigilmon catches this where process monitors cannot.

| Monitor Type | What It Covers | |---|---| | HTTP monitor on /health/warpdb | Platform liveness, ingest path, query path | | HTTP monitor on /api/v0/check | Native WarpDB liveness for each node | | Heartbeat monitor | Ingestion pipeline continuity |

Get started free at vigilmon.online — your first WarpDB monitor takes under two minutes to configure.

Monitor your app with Vigilmon

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

Start free →