Skip to content

Add LogView: record and export Control Hub logs from the dashboard - #218

Open
vik-j wants to merge 4 commits into
acmerobotics:masterfrom
6165-MSET-Cuttlefish:logView
Open

vik-j wants to merge 4 commits into
acmerobotics:masterfrom
6165-MSET-Cuttlefish:logView

Conversation

@vik-j

@vik-j vik-j commented Jul 22, 2026 •

Copy link
Copy Markdown

Add LogView: record and export Control Hub logs from the dashboard

Summary

Adds a new Log view that captures the Control Hub's device logs live in the dashboard — start recording, run your op mode, stop, then preview inline or download the
session as a .log file. This replaces the round-trip of pulling logs off the hub over ADB. The recording window is bounded and configurable so long sessions stay
manageable.

What's included

Recording workflow

  • Start/stop recording from the Log view. Start begins capturing the live logcat stream; stop finalizes the session with start/stop timestamps.
  • Recordings are kept to a rolling window of the most recent N lines (default 10,000). When older lines are dropped, the session is flagged as truncated so you know the
    capture was clipped.

Preview & export

  • Recordings of 500 lines or fewer render inline with color-coded levels (VERBOSE/DEBUG/INFO/WARN/ERROR), timestamps, and tags; longer ones are download-only to keep the
    UI responsive.
  • Any non-empty recording downloads as a plain-text .log file (with an entry count and a truncation note in the header); a clear button discards the session.
  • Capture state lives in a dedicated logRecorder Redux slice, so it survives view/layout changes.

Configurable limit

  • A new Logging section in the Settings dialog sets the max recorded entries (default 10,000, clamped 100–100,000, persisted in localStorage). Lowering the limit trims
    an in-progress recording immediately. The active limit is surfaced on the Log view's idle screen and recording header.

Integration

  • Registered in the ConfigurableView enum (appended last to keep saved custom layouts valid), ConfigurableLayout's view map, and the ViewPicker.
  • Adds a Log layout preset — identical to the Field preset with the field block swapped for the Log view — selectable from the header dropdown.
  • New stop.svg icon in the repo's Material style.

Control Hub log capture (server side)

The dashboard's Java side (FtcDashboard.java) runs a logcat monitor and streams parsed entries to the client. This branch also fixes that monitor so it actually works
against real hardware (it previously only produced output against the mock server):

  • Format: spawns logcat -v threadtime — pinning the format the parser expects (the default brief format silently failed every line).
  • Scope: captures the full device log (all tags/levels) instead of a single tag, so op-mode lifecycle messages and user RobotLog calls (logged under RobotCore, not
    OpModeManager) actually show up.
  • Flushing: sends parsed entries as soon as the stream drains (or every 50 lines) instead of waiting for a fixed batch, so sparse output isn't stuck in a buffer.
  • Levels: maps logcat's single-letter levels (E/W/I/…) to the full-word levels the client color-codes on.
  • Diagnostics: emits synthetic started / failed / stopped markers straight to the client, so a silent Log view can be distinguished from a dead monitor thread.

Local testing without a robot

TestDashboardInstance includes a fake logcat emitter (a random OpModeManager line every 1–2 s), and a new :DashboardCore:testServer Gradle task lets you exercise the
full record → stop → preview/download flow with ./gradlew :DashboardCore:testServer plus npm run dev in client/.

Files changed

  • Client: LogView/LogView.tsx (new view), store/{actions,reducers,types}/logRecorder.* (new slice), store/reducers/index.ts, Dashboard/SettingsModal.tsx (Logging
    section), ConfigurableLayout/{ConfigurableLayout,ViewPicker}.tsx, enums/{ConfigurableView,LayoutPreset}.tsx, assets/icons/stop.svg.

  • Server: FtcDashboard.java (logcat monitor + fixes), TestDashboardInstance.java (mock emitter), DashboardCore/build.gradle (testServer task).

    Testing

  • Exercised the full record → stop → inline-preview and download flow against the mock server.

  • Verified level color-coding, the truncation flag, and that lowering the max-entries limit trims an active recording.

  • Verified on real hardware — the Control Hub capture fixes are based on tracing the SDK's own RobotLog logcat usage; the broad-capture behavior and monitor

Screen.Recording.2026-07-21.at.9.mp4

vik-j and others added 3 commits July 19, 2026 02:39
…ownload, and inline preview

Adds a new LogView that lets users capture Control Hub logs directly from the dashboard. Pressing start begins recording the existing logcat stream
  (RECEIVE_LOGCAT_ERRORS messages already sent by FtcDashboard.java); pressing stop compiles the captured window into a session with start/stop timestamps. Recordings of
  500 lines or fewer can be viewed inline with color-coded levels, timestamps, and tags; longer ones are download-only. Any non-empty recording can be downloaded as a
  plain-text .log file, and a clear button discards the session.

  Capture state lives in a new logRecorder redux slice so it survives view and layout changes. Recordings are kept to a rolling window of the most recent N lines, where N
  is user-configurable via a new "Logging" section in the Settings dialog (default 10,000, clamped 100–100,000, persisted in localStorage); lowering the limit trims an
  in-progress recording immediately. LogView surfaces the active limit on its idle screen and recording header, notes where to change it, and flags truncated recordings.

  The view is registered in the ConfigurableView enum (appended last to keep saved custom layouts valid), ConfigurableLayout's view map, and the ViewPicker, and a new
  "Log" layout preset — identical to the Field preset with the field block replaced by LogView — is selectable from the header dropdown.

  Testing without a robot: the mock server (TestDashboardInstance.java) now includes a fake logcat emitter that sends a randomly generated OpModeManager line (random level
  and message) every 1–2 seconds, plus a new :DashboardCore:testServer gradle task, so the full record → stop → preview/download flow can be exercised locally with
  ./gradlew :DashboardCore:testServer and npm run dev in client/. Also adds stop.svg in the repo's Material icon style.
  Fix LogView capturing no logs from a real Control Hub

  The logcat monitor worked against the mock server but produced nothing on
  real hardware. Four issues in LogcatMonitorRunnable:

  - Spawned logcat with the default "brief" format while parseLogcatLine
    expected "threadtime"; every line failed to parse. Pin -v threadtime,
    matching the SDK's own RobotLog capture.
  - Only flushed after buffering 10 lines, with the remainder flushed just
    on loop exit, so sparse output stayed stuck in the buffer. Now flush at
    50 lines or as soon as the stream drains (reader.ready()), and drop the
    per-line 50ms sleep.
  - Filtered to the "OpModeManager" tag, but opmode lifecycle and user
    RobotLog calls log under "RobotCore". Capture all tags/levels
    (logcat -v threadtime) so the full device log is shown, not just errors.
  - Reported single-letter levels (E/W/I/...) while the client color-codes
    full words; map them to ERROR/WARN/INFO/DEBUG/VERBOSE.

  Also emit synthetic started/failed/stopped markers straight to the client
  so a silent view can be told apart from a dead monitor thread.
mxtmx added a commit to 6165-MSET-Cuttlefish/slothboard that referenced this pull request Sep 23, 2026
# Conflicts:
#	DashboardCore/build.gradle
#	FtcDashboard/src/main/java/com/acmerobotics/dashboard/FtcDashboard.java
#	client/src/components/Dashboard/SettingsModal.tsx
mxtmx added a commit to 6165-MSET-Cuttlefish/slothboard that referenced this pull request Sep 30, 2026

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants