Skip to main content

Logs and monitoring

Backend logs​

One logging configuration, built by EMAW_BACKEND/logging_utils.py, applies everywhere. Handlers are on the root logger only.

OutputWhatWhere
stdouteverything (always on)`docker compose logs -f django
app.loggeneral application loglog_data volume → /app/logs/ in the containers
error.logwarnings and errorssame
security.logevents written through EMAW.security_log.audit() (logins, verification, staff actions)same
access line per requestmethod, path, status, duration, request id (from RequestLoggingMiddleware)app.log / stdout; gunicorn's own access log is disabled

Files rotate via concurrent-log-handler (multiprocess-safe). Variables: LOG_DIR (default logs/, /app/logs in Docker), DJANGO_LOG_LEVEL, LOG_TO_FILE (0 for stdout only), LOG_JSON (structured lines), TRUST_CF_CONNECTING_IP (real client IP behind the tunnel).

docker compose exec django tail -n 200 /app/logs/error.log
docker compose exec django grep <request-id> /app/logs/app.log

What is never logged​

Emails, tokens, verification codes, passwords and request bodies. The formatter redacts JWTs, emails and Stripe keys as a backstop. Log user ids. Use %s lazy formatting.

Following one request​

Every response carries X-Request-ID. The Admin CRM shows it on error toasts; ask the staff member for it, then grep the backend logs. Celery propagates the id into task logs, so an order's webhook, CRM link, email and Deposco submission share it.

Frontend and mobile​

  • Cloudflare Pages / Workers: deployment logs in the Cloudflare dashboard; the CRM Worker has live logs under Workers → emaw-admin → Logs.
  • The CRM's ESLint forbids console.log because bodies can contain personal data; errors go to toasts with the request id.
  • Mobile: adb logcat, Xcode console; the axios instance logs requests in development only. Crash reporting comes from the store consoles (Google Play vitals, App Store Connect crashes). No crash SDK is installed.

External dashboards​

ServiceShows
Stripe Dashboard → Developers → Webhooksfailed deliveries to the webhook; retry from there
Azure Communication Services → Email → Insightscampaign delivery, bounces
Cloudflare → Zero Trust → Tunnelswhether a connector is up for dev.emaw-app.com / app.emaw-app.com (and how many: two means someone has the dev tunnel)
Cloudflare → Workers & Pages → project → Deploymentslast deploy, build logs
Azure Portal → VM → MetricsCPU, disk; the dev DB VM's disk is worth watching
Expo → project → Updates / Buildswhat mobile users are running

What does not exist yet​

  • No uptime check on app.emaw-app.com or the frontends.
  • No alerting on error.log or Celery failures.
  • No centralised log shipping; logs stay on the VMs.
  • No crash reporting SDK in the mobile app.

These are candidates for the known gaps list and the modernization roadmap's "monitoring, alerts and incident response" item.