Skip to content

SLM GUI has no application-log visibility — /api/monitoring/logs only serves fleet node events, not backend/frontend error logs #11302

Closed

Description

@mrveiss

Observed (E2E via builtin tools only)

The only builtin log surface — GET /slm/api/monitoring/logs (autobot-slm-backend/api/monitoring.py:746), which the SLM GUI's log view uses — returns fleet/node health events only:

  • severity=error&limit=10 → 1 result: {"event_type":"health_check","message":"Node status changed from online to error"}.
  • No access to the actual application error logs (/var/log/autobot/backend-error.log, celery-error.log, rum.log) — tracebacks, HTTP 500s, UndefinedColumnError, ImportError, etc.

Impact

Operators can't diagnose app-level failures from the GUI. Real incidents this session — Company OS 500s (unapplied migration), the Ollama ImportError/provider registration failure, the CEO-chat "no available provider" — were invisible to the builtin log view; they could only be found via shell on the box. "Loop through the logs" is not possible with builtin tooling.

Ask

Add a builtin application-log endpoint/view (tail + filter by service/severity/since over backend-error.log / celery-error.log / rum.log), surfaced in the SLM GUI alongside the fleet events. Redact secrets; paginate.

Activity

  1. mrveiss commented on Jul 22, 2026

    @mrveiss
    OwnerAuthor

    PRD — Application-log visibility in the SLM GUI

    Problem

    GET /slm/api/monitoring/logs (autobot-slm-backend/api/monitoring.py:745) queries only the NodeEvent table (select(NodeEvent)…, lines 758–786) — fleet/node health events. It has no path to real application logs. Those are written by systemd to files, not the DB:

    • backend-error.log — ansible/roles/backend/templates/autobot-backend.service.j2:50 (StandardError=append:{{ backend_log_dir }}/backend-error.log)
    • celery-error.log — autobot-celery.service.j2:44; celery-beat-error.log — autobot-celery-beat.service.j2:50; mcp-bridge-%i-error.log; chromadb-error.log
    • backend_log_dir default /var/log/autobot (ansible/roles/backend/defaults/main.yml:13)

    Frontend surface: MonitoringView.vue:33 (logs tab) → LogViewer.vue → useSlmApi.ts:806 (GET /monitoring/logs). So the GUI's only log view shows fleet events; tracebacks/500s/ImportErrors are invisible without SSH.

    Goal / non-goals

    • Goal: a builtin endpoint + GUI view to tail/filter real application logs (service, severity, since, text) with secret redaction and pagination, alongside the existing fleet events.
    • Non-goals: log aggregation/retention infra, alerting rules, editing/rotating logs, replacing systemd/journald.

    User stories

    1. As an operator, I filter backend-error.log by severity=error since=1h in the GUI and read the traceback — no SSH.
    2. As an operator, I pick a service (backend / celery / celery-beat / mcp-bridge / chromadb) and tail its error log live.
    3. As an operator, I search log text (e.g. ImportError) across a service and paginate results.
    4. As a security-conscious operator, secrets/tokens in log lines are redacted before they reach my browser.

    Functional requirements

    • New endpoint (e.g. GET /api/monitoring/app-logs) — params: service, severity, since/hours, q (text), page, per_page; bounded tail (cap bytes/lines read).
    • Server-side allowlist of readable files under backend_log_dir (no arbitrary path traversal).
    • Redaction pass reusing existing secret-redaction util before serialization.
    • New GUI sub-view/tab in MonitoringView.vue + LogViewer.vue, service/severity/since filters, paginated virtualized list.
    • Auth: same get_current_user gate as /logs; consider admin-only RBAC (open question).

    UX / API surface

    • API: GET /slm/api/monitoring/app-logs (LogsResponse-shaped: entries + total + page + per_page). Reuse LogEntry-style DTO.
    • UI entry: Monitoring → Logs → new "Application logs" segment (SLM frontend is single-locale — no 11-locale i18n needed here; still route all strings through the SLM i18n layer).

    Success criteria

    • With a seeded traceback in backend-error.log, the GUI shows it filtered by service=backend severity=error within one refresh.
    • A line containing a token renders redacted.
    • Path-traversal / non-allowlisted service value → 400, no file read.
    • Reading a large log is bounded (no full-file load; verifiable via response cap).

    Risks / open questions (OWNER decides)

    • Architecture — where do the logs physically live? SLM backend is the control plane; backend-error.log etc. are written on managed nodes, not necessarily the SLM host (architecture_two_backends). Does this view read (a) SLM-host-local logs only, (b) per-node via an agent/SSH/journald API, or (c) a forwarded store? LogForwardingSettings.vue exists — is forwarding the intended source? This choice drives the whole design.
    • RBAC: admin-only, or any authenticated operator?
    • Retention/volume: tail-only, or persist/index for historical search?
    • journald vs raw files as the read source.

    Status: PRD drafted for review — not yet approved for build.

  2. mrveiss commented on Jul 23, 2026

    @mrveiss
    OwnerAuthor

    ✅ Design confirmed (owner approved) — reuse /nodes/{node_id}/execute file-read path

    Key finding: a per-node service-logs endpoint already exists (GET /nodes/{node_id}/services/{service_name}/logs, services.py:701) but runs journalctl -u <svc> — which misses the real app logs. The backend/celery/etc. services redirect stdout+stderr to files via systemd StandardError=append:/var/log/autobot/*-error.log (autobot-backend.service.j2 etc.), bypassing journald. So journalctl shows only unit start/stop noise; tracebacks live only in the *.log files. #11302 is therefore a real gap.

    Confirmed source (owner): read the log files per node via the existing guarded execute primitive (nodes_execution.py, POST /nodes/{node_id}/execute, Issue #3406) which already allows tail/cat/head on /var/log/ with allowlist + path-traversal + sensitive-path guards + admin.system RBAC + audit. No new file-reading surface.

    Build:

    • GET /slm/api/monitoring/app-logs?node_id&service&severity&hours&q&page&per_page — maps service (backend|celery|celery-beat|mcp-bridge|chromadb) → allowlisted file under backend_log_dir; runs bounded tail on the node via the execute internals; parses → LogEntry-shaped DTOs; redacts secrets; filters severity/text/since; paginates. RBAC admin.system. Non-allowlisted service → 400.
    • SLM GUI: Monitoring → Logs → new "Application logs" segment (node picker + service + severity/since/text filters + paginated list). Strings via SLM i18n (en.json); SLM frontend is single-locale.

    Moving to build.

  3. github-actions commented on Jul 23, 2026

    @github-actions
    Contributor

    PR #12188 (merged to Dev_new_gui) references this issue with a close keyword.

    feat(slm): application-log viewer — tail app-log files per node via guarded execute (#11302)

    If this issue is fully resolved, close it manually. If work remains, no action is needed.

  4. mrveiss commented on Jul 23, 2026

    @mrveiss
    OwnerAuthor

    ✅ Delivered in PR #12188 (merged to Dev_new_gui). New GET /slm/api/monitoring/app-logs reads real app-log files per node via the guarded /nodes execute primitive (allowlist + redaction + ADMIN_SYSTEM RBAC), surfaced as an 'Application Logs' tab in the SLM GUI. 187 backend tests pass. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions