Doccano is a self-hosted text annotation platform for building NLP training datasets — supporting named entity recognition (NER), text classification, sentiment analysis, relation extraction, and sequence-to-sequence tasks. ML teams use it to collaboratively label documents before training models. When Celery workers stall, Redis drops, or the document import endpoint fails, annotation jobs queue silently and ML pipelines waiting for exported datasets are blocked. Vigilmon keeps continuous watch over the Django app server, PostgreSQL, Celery, Redis, the projects API, document import and export endpoints, and TLS certificate expiry — so a broken annotation pipeline pages you before it delays a model training run.
What You'll Set Up
- HTTP uptime monitor for the Doccano web UI (port 8000)
- PostgreSQL database connectivity heartbeat
- Celery worker availability heartbeat
- Redis connectivity monitor (Celery broker)
- Projects API health check
- Document import endpoint monitor
- Annotation export service health check
- User authentication service monitor
- Task queue depth monitoring
- TLS certificate expiry alert
Prerequisites
- Doccano running via Docker Compose or natively, accessible on port 8000
- Redis running as the Celery broker
- PostgreSQL configured as the Doccano database
- SSH access to the Doccano host for scripted health checks
- A free Vigilmon account
Step 1: Monitor the Doccano Web UI
Doccano's Django application serves the annotation interface on port 8000. A crash here blocks all annotators from accessing their projects.
- Log in to vigilmon.online and click Add Monitor.
- Set Type to
HTTP / HTTPS. - Enter your Doccano URL:
http://your-server-ip:8000. - Set Check interval to
1 minute. - Set Expected HTTP status to
200. - Click Save.
If Doccano is behind a reverse proxy:
https://doccano.yourdomain.com
For a richer health signal, monitor the React app's asset bundle (confirms static file serving is healthy):
http://your-server-ip:8000/static/js/main.chunk.js
Or check the backend API root directly:
- In Vigilmon, click Add Monitor → HTTP / HTTPS.
- Enter:
http://your-server-ip:8000/v1/health. - Set Expected HTTP status to
200. - Click Save.
Step 2: Monitor PostgreSQL Database Connectivity
Doccano stores projects, documents (examples), annotations, users, and label sets in PostgreSQL. A database outage drops all annotation operations — users can open the UI but cannot load projects or save annotations.
#!/bin/bash
# /usr/local/bin/doccano-db-check.sh
HEARTBEAT_URL="https://vigilmon.online/heartbeat/YOUR_DB_HEARTBEAT_ID"
DB_HOST="${DOCCANO_DB_HOST:-localhost}"
DB_PORT="${DOCCANO_DB_PORT:-5432}"
DB_NAME="${DOCCANO_DB_NAME:-doccano}"
DB_USER="${DOCCANO_DB_USER:-doccano}"
if pg_isready -h "$DB_HOST" -p "$DB_PORT" -d "$DB_NAME" -U "$DB_USER" -q; then
curl -s "$HEARTBEAT_URL"
else
echo "PostgreSQL not ready for Doccano"
fi
- In Vigilmon, click Add Monitor → Cron Heartbeat.
- Set expected interval to
2 minutes.
Schedule:
crontab -e
*/2 * * * * /usr/local/bin/doccano-db-check.sh
Step 3: Monitor Celery Worker Availability
Doccano uses Celery workers for background task processing — dataset import from CSV/JSON/JSONL, bulk annotation operations, and dataset export for ML pipeline consumption. If Celery workers go offline, import and export operations submitted through the UI hang indefinitely with no error feedback to users.
#!/bin/bash
# /usr/local/bin/doccano-worker-check.sh
HEARTBEAT_URL="https://vigilmon.online/heartbeat/YOUR_WORKER_HEARTBEAT_ID"
# Inspect Celery workers — check for active worker response
WORKER_STATUS=$(celery -A config inspect ping --timeout 10 2>/dev/null)
if echo "$WORKER_STATUS" | grep -q "pong"; then
curl -s "$HEARTBEAT_URL"
else
echo "No Doccano Celery workers responding to ping"
fi
If using Docker Compose, target the worker container:
#!/bin/bash
HEARTBEAT_URL="https://vigilmon.online/heartbeat/YOUR_WORKER_HEARTBEAT_ID"
if docker exec doccano-worker celery -A config inspect ping --timeout 10 2>/dev/null | grep -q "pong"; then
curl -s "$HEARTBEAT_URL"
fi
- In Vigilmon, click Add Monitor → Cron Heartbeat.
- Set expected interval to
5 minutes.
Schedule:
*/5 * * * * /usr/local/bin/doccano-worker-check.sh
Step 4: Monitor Redis Connectivity
Redis is Doccano's Celery broker. If Redis goes offline, no new import or export tasks can be queued — the UI shows a spinner while Celery silently stops receiving work.
Add a direct TCP port monitor:
- In Vigilmon, click Add Monitor → TCP Port.
- Enter your server hostname and port
6379. - Set Check interval to
1 minute. - Click Save.
Add a deeper heartbeat that verifies Redis is accepting commands:
#!/bin/bash
# /usr/local/bin/doccano-redis-check.sh
HEARTBEAT_URL="https://vigilmon.online/heartbeat/YOUR_REDIS_HEARTBEAT_ID"
REDIS_HOST="${REDIS_HOST:-localhost}"
REDIS_PORT="${REDIS_PORT:-6379}"
RESPONSE=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" PING 2>/dev/null)
if [ "$RESPONSE" = "PONG" ]; then
curl -s "$HEARTBEAT_URL"
else
echo "Redis PING failed: $RESPONSE"
fi
Schedule every 2 minutes:
*/2 * * * * /usr/local/bin/doccano-redis-check.sh
Step 5: Monitor the Projects API
The projects listing API at GET /v1/projects is the entry point for all Doccano automation — CI/CD scripts, annotation management tools, and integration clients all start by listing available projects. This endpoint exercises the database, authentication middleware, and REST framework simultaneously.
- In Vigilmon, click Add Monitor → HTTP / HTTPS.
- Enter:
http://your-server-ip:8000/v1/projects. - Set Expected HTTP status to
200(if you embed credentials) or401(unauthenticated probe — confirms the API layer is responding). - Set Check interval to
2 minutes. - Click Save.
For an authenticated check with body validation:
#!/bin/bash
# /usr/local/bin/doccano-projects-check.sh
HEARTBEAT_URL="https://vigilmon.online/heartbeat/YOUR_PROJECTS_HEARTBEAT_ID"
DOCCANO_URL="http://localhost:8000"
DOCCANO_USER="${DOCCANO_ADMIN_USER:-admin}"
DOCCANO_PASS="${DOCCANO_ADMIN_PASS:-password}"
# Obtain token
TOKEN=$(curl -s -m 10 -X POST \
-H "Content-Type: application/json" \
-d "{\"username\":\"$DOCCANO_USER\",\"password\":\"$DOCCANO_PASS\"}" \
"$DOCCANO_URL/v1/auth/login/" | python3 -c "import json,sys; print(json.load(sys.stdin).get('key',''))" 2>/dev/null)
if [ -n "$TOKEN" ]; then
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -m 10 \
-H "Authorization: Token $TOKEN" \
"$DOCCANO_URL/v1/projects")
if [ "$HTTP_CODE" = "200" ]; then
curl -s "$HEARTBEAT_URL"
fi
fi
Schedule every 5 minutes:
*/5 * * * * /usr/local/bin/doccano-projects-check.sh
Step 6: Monitor the Document Import Service
Document import — POST /v1/projects/:id/examples — is the pipeline entry point for adding text samples to annotate. Import failures block dataset growth: if the import endpoint is down, ML teams cannot add new batches of text for annotation.
#!/bin/bash
# /usr/local/bin/doccano-import-check.sh
HEARTBEAT_URL="https://vigilmon.online/heartbeat/YOUR_IMPORT_HEARTBEAT_ID"
DOCCANO_URL="http://localhost:8000"
DOCCANO_USER="${DOCCANO_ADMIN_USER:-admin}"
DOCCANO_PASS="${DOCCANO_ADMIN_PASS:-password}"
PROJECT_ID="${DOCCANO_TEST_PROJECT_ID:-1}"
# Authenticate
TOKEN=$(curl -s -m 10 -X POST \
-H "Content-Type: application/json" \
-d "{\"username\":\"$DOCCANO_USER\",\"password\":\"$DOCCANO_PASS\"}" \
"$DOCCANO_URL/v1/auth/login/" | python3 -c "import json,sys; print(json.load(sys.stdin).get('key',''))" 2>/dev/null)
if [ -z "$TOKEN" ]; then
echo "Authentication failed"
exit 1
fi
# Check examples endpoint (GET instead of POST to avoid creating test data)
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -m 10 \
-H "Authorization: Token $TOKEN" \
"$DOCCANO_URL/v1/projects/$PROJECT_ID/examples?limit=1")
if [ "$HTTP_CODE" = "200" ]; then
curl -s "$HEARTBEAT_URL"
else
echo "Import endpoint returned HTTP $HTTP_CODE"
fi
- In Vigilmon, click Add Monitor → Cron Heartbeat.
- Set expected interval to
10 minutes.
Schedule:
*/10 * * * * /usr/local/bin/doccano-import-check.sh
Step 7: Monitor the Annotation Export Service
Export tasks — triggered via the Doccano UI or API and executed by Celery — produce JSON, CSV, or JSONL files consumed by ML training pipelines. A stalled export pipeline is invisible: the UI shows the export as "pending" or "processing" indefinitely while the ML pipeline waits downstream.
Create a heartbeat that verifies the export API endpoint is accessible and Celery workers are completing export tasks:
#!/bin/bash
# /usr/local/bin/doccano-export-check.sh
HEARTBEAT_URL="https://vigilmon.online/heartbeat/YOUR_EXPORT_HEARTBEAT_ID"
DOCCANO_URL="http://localhost:8000"
DOCCANO_USER="${DOCCANO_ADMIN_USER:-admin}"
DOCCANO_PASS="${DOCCANO_ADMIN_PASS:-password}"
PROJECT_ID="${DOCCANO_TEST_PROJECT_ID:-1}"
# Authenticate
TOKEN=$(curl -s -m 10 -X POST \
-H "Content-Type: application/json" \
-d "{\"username\":\"$DOCCANO_USER\",\"password\":\"$DOCCANO_PASS\"}" \
"$DOCCANO_URL/v1/auth/login/" | python3 -c "import json,sys; print(json.load(sys.stdin).get('key',''))" 2>/dev/null)
if [ -z "$TOKEN" ]; then
echo "Authentication failed"
exit 1
fi
# Trigger a small export and verify it completes
TASK_ID=$(curl -s -m 15 -X POST \
-H "Authorization: Token $TOKEN" \
-H "Content-Type: application/json" \
-d '{"exportFormat":"JSONL","exportFileName":"health_check_export.jsonl"}' \
"$DOCCANO_URL/v1/projects/$PROJECT_ID/export" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('id',''))" 2>/dev/null)
if [ -n "$TASK_ID" ]; then
# Task was accepted by Celery queue
curl -s "$HEARTBEAT_URL"
else
echo "Export task submission failed"
fi
- In Vigilmon, click Add Monitor → Cron Heartbeat.
- Set expected interval to
30 minutes.
Schedule:
*/30 * * * * /usr/local/bin/doccano-export-check.sh
Step 8: Monitor User Authentication
Doccano uses Django's token authentication. If the auth service fails — due to a database connectivity issue or Django misconfiguration — users cannot log in and all API clients lose access simultaneously.
- In Vigilmon, click Add Monitor → HTTP / HTTPS.
- Enter:
http://your-server-ip:8000/v1/auth/login/. - Set Expected HTTP status to
405(GET on a POST-only endpoint — confirms the URL is routable and Django is handling requests). - Set Check interval to
2 minutes. - Click Save.
A 405 Method Not Allowed response on a GET to /v1/auth/login/ is the correct indicator: it proves Django's URL routing and authentication middleware are operational without requiring credentials in the monitor.
Step 9: Monitor Task Queue Depth
A growing Celery task queue indicates worker saturation — import and export tasks are queuing faster than workers consume them. This manifests as increasingly long waits for dataset operations and eventually user-visible timeouts.
#!/bin/bash
# /usr/local/bin/doccano-queue-check.sh
HEARTBEAT_URL="https://vigilmon.online/heartbeat/YOUR_QUEUE_HEARTBEAT_ID"
REDIS_HOST="${REDIS_HOST:-localhost}"
QUEUE_NAME="${DOCCANO_CELERY_QUEUE:-celery}"
MAX_DEPTH=50
# Get the queue depth from Redis
QUEUE_DEPTH=$(redis-cli -h "$REDIS_HOST" LLEN "$QUEUE_NAME" 2>/dev/null)
if [ -z "$QUEUE_DEPTH" ]; then
echo "Could not query Redis queue depth"
exit 1
fi
if [ "$QUEUE_DEPTH" -le "$MAX_DEPTH" ]; then
curl -s "$HEARTBEAT_URL"
else
echo "Celery queue depth is $QUEUE_DEPTH — above threshold of $MAX_DEPTH"
fi
- In Vigilmon, click Add Monitor → Cron Heartbeat.
- Set expected interval to
5 minutes.
Schedule:
*/5 * * * * /usr/local/bin/doccano-queue-check.sh
Step 10: Monitor TLS Certificate Expiry
If Doccano is exposed over HTTPS, an expired certificate blocks annotators and API clients immediately.
- In Vigilmon, open your web UI monitor from Step 1.
- Enable Monitor SSL certificate.
- Set Alert when certificate expires in less than
21 days. - Click Save.
For a dedicated certificate monitor:
- In Vigilmon, click Add Monitor → HTTP / HTTPS.
- Enter:
https://doccano.yourdomain.com. - Enable Monitor SSL certificate with a
21 dayalert. - Set Check interval to
1 hour. - Click Save.
Step 11: Configure Alert Channels
- Go to Alert Channels in Vigilmon and add Slack, email, or a webhook.
- Set Consecutive failures before alert to
2on the web UI monitor — Django restarts briefly. - Set Consecutive failures before alert to
1on Redis and Celery monitors — a broken broker immediately stalls all import and export jobs.
Route failures by urgency:
- Redis down, Celery workers silent → Slack #doccano-critical (immediate — no import/export possible)
- Web UI down, database unreachable → Slack #doccano-alerts (urgent)
- Queue depth spike, TLS expiry → email (investigate within hours)
Summary
| Monitor | Target | What It Catches |
|---|---|---|
| Web UI | http://server:8000 | Django process crash |
| PostgreSQL | pg_isready heartbeat | Data store unavailable |
| Redis TCP | Port 6379 | Celery broker offline |
| Celery workers | celery inspect ping | Import/export pipeline dead |
| Projects API | GET /v1/projects | REST layer failure |
| Document import | GET /v1/projects/:id/examples | Import endpoint failure |
| Export service | Export task heartbeat | Celery export task stall |
| Auth service | GET /v1/auth/login/ 405 | Authentication layer failure |
| Queue depth | Redis LLEN | Worker saturation |
| TLS certificate | HTTPS endpoint | Certificate expiry |
Doccano's annotation pipeline runs end-to-end through import → annotate → export — and Celery is the engine that drives both ends of that pipeline. With Vigilmon monitoring Redis, Celery workers, and the import/export endpoints, a stalled OCelery queue or dropped Redis connection alerts you immediately instead of silently blocking an ML training run.