OpenMates Docs Open Chat

Admin Console Log Forwarding

Admin Console Log Forwarding Browser console logs from admin users are forwarded in real-time to OpenObserve via a backend proxy, providing unified client+se...

[T:documentation.sender_name]

Admin Console Log Forwarding

Browser console logs from admin users are forwarded in real-time to OpenObserve via a backend proxy, providing unified client+server observability.

Why This Exists

Debugging client-side issues requires seeing browser logs alongside server logs. Admin-only forwarding keeps the feature scoped (no regular user data leaves the browser) while providing a unified timeline in OpenObserve.

How It Works

Architecture

Browser (admin only)
  logCollector.ts       -- patches console.{log,info,warn,error,debug}
  clientLogForwarder.ts -- batches every 5s, durable IndexedDB queue
      | POST /v1/admin/client-logs (credentials: include, keepalive: true)
  FastAPI (admin_client_logs.py)
      | Loki-compat push (aiohttp)
  OpenObserve :5080 (stream: "client-console", job="client-console")

Playwright E2E runs use the same collector and queue, but when the page is loaded with #e2e-debug=...&e2e-token=..., clientLogForwarder.ts sends the main queue only to POST /e2e/client-logs with X-E2E-Debug-Token. It intentionally skips the admin endpoint in E2E mode so admin test accounts do not produce browser CORS errors while the test-only log capture path remains active.

Forwarder Lifecycle

Event Action
Login with is_admin: true clientLogForwarder.start()
Session restore with is_admin clientLogForwarder.start()
Logout clientLogForwarder.stop() (drains first)
Session expiry clientLogForwarder.stop()
E2E debug hash detected clientLogForwarder.startE2E()

The is_admin flag comes from /v1/auth/login and /v1/auth/session responses, sourced from the Redis user profile cache. When admin status changes via AdminMethods.make_user_admin() / revoke_admin_privileges(), the cache key is deleted immediately.

Batching

  • Flush interval: 5 seconds
  • Max batch size: 50 entries
  • Max batches per flush cycle: 25
  • Durable IndexedDB queue (openmates_admin_client_log_queue) survives page refreshes

Privacy

  • Non-admin users: forwarder never starts. Logs stay in logCollector circular buffers; only sent on explicit issue submission.
  • Messages sanitized client-side: API keys (sk-api-*), bearer tokens, and common sensitive fields redacted.
  • OpenObserve endpoint never exposed to browser – all pushes go through the backend proxy.

Querying in OpenObserve

SELECT _timestamp, user_email, level, message
FROM "client-console"
WHERE _timestamp > NOW() - INTERVAL '1 hour'
ORDER BY _timestamp DESC

Stream labels: job="client-console", level, user_email, server_env, source="browser".

Environment Variables

Variable Where Purpose
OPENOBSERVE_ROOT_EMAIL Backend Basic auth for server-side push
OPENOBSERVE_ROOT_PASSWORD Backend Basic auth for server-side push

Edge Cases

  • If IndexedDB is unavailable (e.g., private browsing), falls back to a volatile in-memory queue.
  • Backend proxy failure: entries remain in IndexedDB queue and are retried on next flush cycle.
  • Logging System – server-side logging architecture
  • Server logs reach OpenObserve via Promtail (Docker socket + file discovery)