Skip to main content

Monitoring

Health Checks​

API Health Endpoint​

The API exposes a health check at GET /api/health:

curl http://localhost:3333/api/health
  • 200 OK — API is healthy and database is reachable
  • 503 Service Unavailable — Database connection failed (2-second timeout)

Docker Healthchecks​

Each service has a Docker healthcheck configured:

ServiceCheckMethod
dbpg_isreadyPostgreSQL readiness probe
apiGET /api/healthHTTP health endpoint
webGET /HTTP response check
schedulerpgrep -f 'node'Process liveness
ai-plannerpgrep -f 'node'Process liveness

Healthcheck timing: interval: 30s, timeout: 5s, retries: 3, start_period: 30s for most services. The database uses a faster cycle: interval: 10s, retries: 5 (no start period).

Checking Status​

# Overview of all services and health status
docker compose ps

# Example output:
# NAME STATUS PORTS
# cronicorn-db Up 2 hours (healthy) 5432/tcp
# cronicorn-api Up 2 hours (healthy) 0.0.0.0:3333->3333/tcp
# cronicorn-scheduler Up 2 hours (healthy)
# cronicorn-web Up 2 hours (healthy)
# cronicorn-migrator Exited (0) 2 hours ago

The migrator showing Exited (0) is normal — it runs once and exits after applying migrations.

Logs​

Viewing Logs​

# All services
docker compose logs -f

# Specific service
docker compose logs -f api

# Last 100 lines
docker compose logs --tail=100 api

# Since a specific time
docker compose logs --since="2025-01-15T10:00:00" api

Log Format​

The API and workers emit structured JSON logs via Pino:

{
"level": 30,
"time": 1705312800000,
"msg": "Request completed",
"requestId": "abc-123",
"userId": "user_456",
"method": "GET",
"path": "/api/endpoints",
"status": 200,
"duration": 42
}

Key Log Fields​

FieldDescription
levelPino log level (30=info, 40=warn, 50=error, 60=fatal)
timeUnix timestamp in milliseconds
msgLog message
requestIdUnique request ID (matches X-Request-Id header)
userIdAuthenticated user ID (if applicable)
methodHTTP method
pathRequest path
statusHTTP response status code
durationRequest duration in milliseconds

Pretty-Printing Logs​

For human-readable logs during debugging:

docker compose logs api | npx pino-pretty

Request Tracing​

Every API request receives a unique X-Request-Id header. Use this to trace a request through logs:

# Get the request ID from a response
curl -v http://localhost:3333/api/health 2>&1 | grep x-request-id

# Search logs for that request
docker compose logs api | grep "abc-123"

You can also pass your own request ID:

curl -H "X-Request-Id: my-trace-123" http://localhost:3333/api/health

Resource Monitoring​

Container Resources​

# Real-time CPU, memory, and network usage
docker stats

# One-shot snapshot
docker stats --no-stream

Disk Usage​

# Check database volume size
du -sh ../files/cronicorndatabasevolume

# Check Docker disk usage
docker system df

Rate Limit Headers​

The API returns rate limit information in response headers:

HeaderDescription
X-RateLimit-LimitMaximum requests per window
X-RateLimit-RemainingRequests remaining in current window
X-RateLimit-ResetSeconds until the rate limit window resets

Monitor these to detect clients approaching rate limits.

External Alerting​

Cronicorn does not include built-in alerting. For production deployments, consider external uptime monitoring:

Point these at your API health endpoint (GET /api/health) for basic availability monitoring.