tutorial

Monitoring MapServer with Vigilmon

MapServer is the battle-tested OGC web mapping engine powering WMS, WFS, and WCS services worldwide — but CGI/FastCGI deployments have no built-in health dashboard. Here's how to monitor MapServer process health, WMS latency, tile cache performance, and PostGIS data source connectivity with Vigilmon.

MapServer is one of the oldest and most widely deployed open source web mapping engines, originally developed at the University of Minnesota and now maintained by OSGeo. It publishes WMS, WFS, WCS, and SOS map services from Shapefiles, PostGIS, GeoTIFF, and dozens of other formats — all via a C application running as CGI or FastCGI under Apache or nginx. That lean architecture is fast and reliable, but it also means there's no management console, no built-in health endpoint, and no alerting when FastCGI workers saturate or a PostGIS layer stops rendering. Vigilmon fills that gap with external probes for WMS availability, rendering latency, tile cache performance, and data source health.

What You'll Set Up

  • WMS GetCapabilities availability monitor
  • WMS GetMap rendering latency alert
  • PostGIS data source connectivity check
  • MapCache tile hit rate monitoring
  • FastCGI worker process heartbeat
  • Mapfile error detection via access log probe

Prerequisites

  • MapServer deployed as CGI or FastCGI under Apache 2.4+ or nginx
  • At least one Mapfile with a working WMS layer
  • Optional: MapCache tile caching accelerator installed
  • A free Vigilmon account

Step 1: Monitor WMS Availability with GetCapabilities

The WMS GetCapabilities request exercises the entire MapServer stack — the web server, CGI/FastCGI worker, Mapfile parsing, and XML serialization — in a single probe:

https://mapserver.yourdomain.com/cgi-bin/mapserv?map=/path/to/your.map&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities

Add a Vigilmon HTTP monitor:

  1. Log in to vigilmon.online and click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. Enter the GetCapabilities URL for your deployment.
  4. Set Expected response contains to WMS_Capabilities.
  5. Set Check interval to 1 minute.
  6. Click Save.

A GetCapabilities response confirms MapServer is running, the Mapfile is loadable, and the WMS layer list is populated. If MapServer crashes or the CGI binary is missing, this probe returns a 500 or a blank response immediately.

For FastCGI deployments, the GetCapabilities probe also confirms that at least one FastCGI worker is alive — a pool where all workers have crashed returns a 503 from nginx/Apache before MapServer even runs.


Step 2: Monitor WMS Rendering Latency

WMS GetMap requests are the core MapServer workload — rendering map images from PostGIS queries, Shapefile reads, or GeoTIFF tiles. Latency spikes indicate PostGIS query slowdowns, large dataset rendering, or FastCGI pool exhaustion.

Build a synthetic WMS GetMap probe with a known small bounding box:

https://mapserver.yourdomain.com/cgi-bin/mapserv?map=/path/to/your.map
  &SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap
  &BBOX=-180,-90,180,90&CRS=EPSG:4326
  &WIDTH=256&HEIGHT=256&LAYERS=your_layer_name&FORMAT=image/png

Add this as a Vigilmon HTTP monitor:

  1. Click Add MonitorHTTP / HTTPS.
  2. Set the URL to your GetMap probe URL above (URL-encode the parameters).
  3. Set Expected HTTP status to 200.
  4. Set Expected response content type to image/png.
  5. Under Advanced, set Alert if response time exceeds to 3000 ms.
  6. Set Check interval to 2 minutes.
  7. Click Save.

A full-world bounding box at 256×256 pixels is a good representative workload — large enough to exercise real data reading but small enough to complete in under a second on healthy hardware. Alert at 3 seconds: that's the threshold where users notice lag in web map clients.


Step 3: Monitor PostGIS Data Source Connectivity

If your MapServer layers read from PostGIS, a database outage causes every PostGIS-backed WMS layer to return blank tiles — with no HTTP error, just empty images. Monitor PostGIS directly with a TCP port check:

  1. Click Add MonitorTCP Port.
  2. Host: your PostgreSQL/PostGIS host.
  3. Port: 5432.
  4. Set Check interval to 1 minute.
  5. Click Save.

Pair this with a synthetic WMS GetMap probe that targets a layer backed by PostGIS (not a Shapefile layer) — if the TCP port is up but PostGIS is rejecting connections due to max_connections exhaustion, the WMS probe latency will spike:

# Quick manual test — measure PostGIS-backed layer rendering time
time curl -s -o /dev/null \
  "https://mapserver.yourdomain.com/cgi-bin/mapserv?map=/path/to/your.map&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=-10,40,10,55&CRS=EPSG:4326&WIDTH=512&HEIGHT=512&LAYERS=postgis_layer&FORMAT=image/png"

If this query takes more than a second on a warm system, your PostGIS query plan or connection pool needs attention.


Step 4: Monitor MapCache Tile Hit Rate

MapCache pre-renders and caches tiles to serve common views without re-running MapServer. A low cache hit rate means every request re-renders — multiplying MapServer load. MapCache exposes stats via a management endpoint:

curl http://localhost/mapcache/?service=demo

For a JSON stats view (MapCache 1.12+):

curl "http://localhost/mapcache/tileset/your_tileset?service=wmts&request=getcapabilities"

Build a monitoring script that queries MapCache stats and reports the hit rate to Vigilmon:

#!/bin/bash
# monitor-mapcache.sh

MAPCACHE_STATS_URL="http://localhost/mapcache/?service=demo"
VIGILMON_KEY="${VIGILMON_API_KEY}"
MONITOR_ID="${VIGILMON_MAPCACHE_MONITOR_ID}"
MIN_HIT_RATE=50  # alert if cache hit rate drops below 50%

# Parse hit/miss counts from MapCache status page
STATS=$(curl -s "$MAPCACHE_STATS_URL")
HITS=$(echo "$STATS" | grep -oP 'hits:\s*\K[0-9]+' | head -1)
MISSES=$(echo "$STATS" | grep -oP 'misses:\s*\K[0-9]+' | head -1)

if [ -z "$HITS" ] || [ -z "$MISSES" ]; then
  echo "Could not parse MapCache stats"
  exit 1
fi

TOTAL=$((HITS + MISSES))
if [ "$TOTAL" -gt 0 ]; then
  HIT_RATE=$((HITS * 100 / TOTAL))
  if [ "$HIT_RATE" -lt "$MIN_HIT_RATE" ]; then
    curl -s -X POST \
      "https://vigilmon.online/api/monitors/${MONITOR_ID}/report" \
      -H "Authorization: Bearer ${VIGILMON_KEY}" \
      -H "Content-Type: application/json" \
      -d "{\"status\":\"down\",\"message\":\"MapCache hit rate ${HIT_RATE}% below threshold ${MIN_HIT_RATE}%\"}"
  fi
fi

Run via cron every 5 minutes. A hit rate below 50% is a strong signal that the tile cache is undersized or the cache seeder hasn't been run for the current zoom levels.


Step 5: FastCGI Worker Process Heartbeat

In FastCGI mode, MapServer pre-spawns worker processes managed by spawn-fcgi or mod_fcgid. If all workers crash, requests queue and eventually return 502 or 503 errors. Use Vigilmon's cron heartbeat to verify the FastCGI pool is healthy:

  1. Click Add MonitorCron Heartbeat.
  2. Set the expected interval to 5 minutes.
  3. Copy the heartbeat URL.

Add a cron job that checks the FastCGI process count and pings Vigilmon only when workers are running:

#!/bin/bash
# check-mapserver-fcgi.sh

HEARTBEAT_URL="https://vigilmon.online/heartbeat/abc123"
MIN_WORKERS=1

WORKER_COUNT=$(pgrep -c mapserv)

if [ "$WORKER_COUNT" -ge "$MIN_WORKERS" ]; then
  curl -s "$HEARTBEAT_URL"
else
  echo "MapServer FastCGI workers not found (count: $WORKER_COUNT)" >&2
  exit 1
fi

Schedule with cron:

*/5 * * * * /opt/scripts/check-mapserver-fcgi.sh

If the FastCGI pool crashes completely, the heartbeat stops firing and Vigilmon alerts within 5–10 minutes (one missed interval).


Step 6: Mapfile Error Detection

MapServer parses the Mapfile on each CGI invocation (or at FastCGI startup). A Mapfile syntax error after a config change causes every WMS request to return a 500 error or a blank MapServer message PNG with an error string embedded.

After any Mapfile change, run the built-in validation:

mapserv -nh "MAP=/path/to/your.map&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities" 2>&1 | grep -i error

Integrate Mapfile validation into your deployment pipeline:

#!/bin/bash
# deploy-mapfile.sh

MAPFILE="/path/to/your.map"

# Validate before deploying
ERRORS=$(mapserv -nh "MAP=${MAPFILE}&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities" 2>&1 | grep -i "error\|msLoad" | wc -l)

if [ "$ERRORS" -gt 0 ]; then
  echo "Mapfile validation failed — aborting deployment"
  mapserv -nh "MAP=${MAPFILE}&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities" 2>&1 | grep -i "error\|msLoad"
  exit 1
fi

# Deploy the validated Mapfile
cp "$MAPFILE" /var/www/mapserver/production.map
echo "Mapfile deployed successfully"

# Ping Vigilmon to confirm successful deployment
curl -s "https://vigilmon.online/heartbeat/deploy-heartbeat-id"

This catches projection syntax errors, missing data file references, and invalid layer configurations before they reach production.


Step 7: Configure Alert Channels

  1. In Vigilmon, go to Alert Channels and add Slack, email, or a webhook.
  2. For the WMS GetCapabilities monitor, set Consecutive failures before alert to 2 — CGI process startup time can cause a single-probe timeout.
  3. For the WMS GetMap latency monitor, set Alert if response time exceeds to 3000 ms.
  4. Use Vigilmon Maintenance windows during MapCache seeding operations, which saturate the MapServer process pool:
curl -X POST https://vigilmon.online/api/maintenance \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "monitor_id": "wms-getmap-monitor-id",
    "duration_minutes": 60,
    "reason": "MapCache seeding zoom levels 0-12"
  }'

Summary

| Monitor | Target | What It Catches | |---|---|---| | WMS GetCapabilities | ?REQUEST=GetCapabilities | MapServer crash, Mapfile parse error | | WMS GetMap latency | ?REQUEST=GetMap (timed) | PostGIS slow queries, pool saturation | | PostGIS TCP | Port 5432 | Database server down | | MapCache hit rate | Stats endpoint script | Cache miss storm, unseeded zoom levels | | FastCGI heartbeat | Process count cron | Worker pool crash | | Mapfile validation | Deployment script | Config error before production push |

MapServer's CGI architecture is refreshingly simple — there's no application server to crash, no JVM heap to tune, no container orchestrator to misconfigure. But that simplicity also means there's no built-in health reporting. With Vigilmon monitoring each layer of the stack, you know within minutes whether a PostGIS query regression, a Mapfile error, or a FastCGI pool exhaustion is breaking the WMS services your GIS clients depend on.

Monitor your app with Vigilmon

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

Start free →