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
- Log in to vigilmon.online and go to Monitors → New Monitor
- Choose HTTP / HTTPS
- Set the URL to your health endpoint:
https://your-app.example.com/health/warpdb - Set the check interval to 1 minute
- Under Expected response, configure:
- Status code:
200 - Response body contains:
"status":"ok" - Response time threshold:
5000ms(WarpDB exec can be slow on large datasets)
- Status code:
- Under Alert channels, assign your Slack or email channel
- 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
- In Vigilmon, go to Monitors → New Monitor → Heartbeat
- Set the name:
warpdb-ingestion-pipeline - Set the expected interval to match your ingestion frequency (e.g., 5 minutes)
- Set the grace period: 10 minutes
- 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:
- Create an HTTP monitor pointing directly to
https://warpdb-node:8080/api/v0/check - Set the expected status code to
200 - 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:
- Ingestion health monitor → immediate Slack + PagerDuty (P1 — data loss)
- Query health monitor → Slack + email (P1 — dashboard blindness)
- 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.