Skip to content
BunBase BunBase BunBase Docs Alpha v0.1.0

Observability

BunBase provides structured logs, Prometheus metrics, and a hot backup endpoint for production operations.

All logs are emitted as JSON to stdout:

{
"level": "info",
"event": "request",
"request_id": "a1b2c3d4-...",
"method": "POST",
"path": "/api/v1/auth/login",
"status": 200,
"latency_ms": 4,
"user_id": "01JKX...",
"ip": "203.0.113.1",
"ts": 1709900000000
}
LevelDescription
debugDetailed internal events
infoNormal operation (default)
warnNon-fatal issues
errorErrors requiring attention
offDisable all logging

Set with LOG_LEVEL env var.

HTTP access logs can be disabled separately:

Terminal window
LOG_ACCESS=off # disable request logs only

Logs are stored in SQLite files under DATA_DIR/logs/. Two pruning policies run every minute:

Row-count cap (always active) — oldest rows are deleted once the table exceeds the limit:

Runtime settingDefaultDescription
access_log_max_rows10000Max rows in the access log
app_log_max_rows10000Max rows in the app log

Age cap (opt-in) — rows older than N days are deleted:

Runtime settingDefaultDescription
access_log_max_age_days0Delete access logs older than N days (0 = disabled)
app_log_max_age_days0Delete app logs older than N days (0 = disabled)

Both policies are applied on every scheduler tick (every 60 seconds). Age-cap is applied after row-cap so both constraints are honoured.

Every request gets a unique request_id (UUID v4). It is returned in the X-Request-Id response header and included in all log entries for that request.

BunBase exposes a Prometheus-compatible /metrics endpoint:

Terminal window
curl http://localhost:8080/metrics
# HELP bunbase_pending_requests Number of in-flight HTTP requests per worker.
# TYPE bunbase_pending_requests gauge
bunbase_pending_requests{worker="0",instance="..."} 3
# HELP bunbase_pending_websockets Number of active WebSocket connections per worker.
# TYPE bunbase_pending_websockets gauge
bunbase_pending_websockets{worker="0",instance="..."} 12
# HELP bunbase_active_workers Number of active HTTP workers in the cluster.
# TYPE bunbase_active_workers gauge
bunbase_active_workers 4
# HELP bunbase_request_latency_p50_ms 50th-percentile request latency (last 1000 requests, this worker).
# TYPE bunbase_request_latency_p50_ms gauge
bunbase_request_latency_p50_ms{worker="0",instance="..."} 2.3
# HELP bunbase_request_latency_p95_ms 95th-percentile request latency (last 1000 requests, this worker).
# TYPE bunbase_request_latency_p95_ms gauge
bunbase_request_latency_p95_ms{worker="0",instance="..."} 12.1
# HELP bunbase_request_latency_p99_ms 99th-percentile request latency (last 1000 requests, this worker).
# TYPE bunbase_request_latency_p99_ms gauge
bunbase_request_latency_p99_ms{worker="0",instance="..."} 45.3
# HELP bunbase_requests_per_minute Number of requests handled in the last completed minute, per worker.
# TYPE bunbase_requests_per_minute gauge
bunbase_requests_per_minute{worker="0",instance="..."} 87
# HELP bunbase_errors_per_minute Number of 5xx responses in the last completed minute, per worker.
# TYPE bunbase_errors_per_minute gauge
bunbase_errors_per_minute{worker="0",instance="..."} 0
# HELP bunbase_info Static server metadata.
# TYPE bunbase_info gauge
bunbase_info{version="0.7.0",bun_version="1.3.10"} 1

Add a Prometheus scrape job:

scrape_configs:
- job_name: bunbase
static_configs:
- targets: ['localhost:8080']
metrics_path: /metrics

Trigger a consistent SQLite backup while the server is live:

POST /api/v1/admin/backup
Authorization: Bearer <admin-secret>

The server streams back a .db file using SQLite’s VACUUM INTO, which produces a clean, defragmented copy with no journal files needed. The backup can be taken under full write load without locking the database.

Terminal window
curl -X POST http://localhost:8080/api/v1/admin/backup \
-H "Authorization: Bearer $ADMIN_SECRET" \
--output backup-$(date +%Y%m%d-%H%M%S).db
bunbase-backup.sh
#!/bin/sh
DATE=$(date +%Y%m%d-%H%M%S)
curl -sf -X POST https://your-domain.com/api/v1/admin/backup \
-H "Authorization: Bearer $ADMIN_SECRET" \
--output /backups/bunbase-$DATE.db
# Keep last 30 backups
ls -t /backups/bunbase-*.db | tail -n +31 | xargs rm -f

Schedule with cron:

0 * * * * /usr/local/bin/bunbase-backup.sh
Terminal window
curl https://your-domain.com/api/v1/admin/health
{
"status": "ok",
"db": "ok",
"uptime_ms": 86400000,
"version": "0.9.0",
"bun_version": "1.2.0"
}

When the DB worker is unreachable, the endpoint returns HTTP 503:

{
"status": "degraded",
"db": "error",
"uptime_ms": 86400000,
"version": "0.9.0",
"bun_version": "1.2.0"
}

Load balancers should check for HTTP 200 to route traffic; they will automatically stop sending requests to instances that return 503.