Skip to content

FIX: Reduce logs panel noise and make execution messages readable (OR-1457)#59

Merged
abhizipstack merged 3 commits intomainfrom
fix/logs-panel-noise-and-meaningful-messages
Apr 16, 2026
Merged

FIX: Reduce logs panel noise and make execution messages readable (OR-1457)#59
abhizipstack merged 3 commits intomainfrom
fix/logs-panel-noise-and-meaningful-messages

Conversation

@abhizipstack
Copy link
Copy Markdown
Contributor

@abhizipstack abhizipstack commented Apr 15, 2026

What

  • Demoted `UsingCachedObject` from `InfoLevel` to `DebugLevel` so the per-query "Using Cached Object of bigquery_connection_object" spam no longer reaches the UI at default verbosity.
  • Fixed `Processing Model : ""` — use `cls.name` (fallback `file_name`) instead of `str(cls)` which was empty for dynamic no-code model classes.
  • Stopped `str(Enum)` from leaking dotted enum names (`ExecStatus.Success`, `Materialization.EPHEMERAL`, etc.) into user-visible messages; use `.value` so the UI shows `SUCCESS` / `OK` / `TABLE`.
  • Fixed the summary counter bug — `parse_and_fire_reports` compared `end_status` against `ExecStatus.Success`/`Error`, but `end_status` is set to `OK`/`Fail`. Counters stayed at zero, so `DONE PASS=0 WARN=0 ERROR=0 SKIP=0 TOTAL=0` showed even after successful runs. Now compares against correct end-status values.
  • Added a log-level selector to the bottom logs tab: `All logs / Info & above / Warnings & errors / Errors only`. Default `Info & above` (hides debug noise out of the box). Choice persists in `localStorage`.
  • Each log row is tinted by severity (grey / default / amber / red) for quick scanning.

Why

Bottom logs panel was dominated by dev-internal debug lines and leaky enum reprs:
```
06:16:09 [info] [ThreadPool]: Processing Model : "".
06:16:09 [info] [ThreadPool]: Executing Model Node: ... Materialization: Materialization.EPHEMERAL ...
06:16:09 [info] [ThreadPool]: 1 of 2 ExecStatus.Success .................................... [ ExecStatus.OK ]
06:16:09 [info] [ThreadPool]: DONE PASS=0 WARN=0 ERROR=0 SKIP=0 TOTAL=0
```
Users couldn't tell what actually happened after an action. After this change, the same run reads:
```
06:16:09 [info] [ThreadPool]: Processing Model : "MModelA".
06:16:09 [info] [ThreadPool]: Executing Model Node: ... Materialization: TABLE ...
06:16:09 [info] [ThreadPool]: 1 of 2 SUCCESS MModelA .......... [ OK ]
06:16:09 [info] [ThreadPool]: DONE PASS=2 WARN=0 ERROR=0 SKIP=0 TOTAL=2
```

How

Backend (`backend/visitran/`)

  • `events/types.py:472` — `UsingCachedObject(InfoLevel) → DebugLevel`.
  • `events/printer.py:89-96` — compare `end_status` to `OK`/`Fail`/`Warn`/`Skipped` values (was comparing to `Success`/`Error`).
  • `visitran.py` — replaced `str(ExecStatus.X)` with `ExecStatus.X.value` everywhere (5 call sites). Same for `node.materialization`.
  • `visitran.py:515` — `ProcessingModel(cls=getattr(cls, "name", "") or file_name)`.

Frontend (`frontend/src/ide/editor/no-code-model/no-code-model.jsx`)

  • Socket handler stores `{ level, message }` (was a raw string) and reads `data?.data?.level`.
  • New `Select` above the logs tab bound to `logsLevel` state, initialized from `localStorage.getItem("visitran.logsLevel") || "info"`.
  • `LOG_LEVEL_RANK` threshold filters the rendered list; `LOG_LEVEL_COLOR` tints rows.

Can this PR break any existing features?

Low risk:

  • Log socket payload already carried `level` — we just started using it. Missing level falls back to `info`.
  • Old string-only entries in `logsInfo` would have crashed the render, but the list starts empty per session and no other writer exists.
  • Enum `.value` change: external consumers that parsed `BaseResult.status == "ExecStatus.Success"` would break, but the only consumer is `parse_and_fire_reports` in the same commit and it's been updated.
  • `UsingCachedObject` demotion to debug means operators who rely on seeing cached-connection hits must select "All logs" (documented via the dropdown label).

Database Migrations

None.

Env Config

None.

Relevant Docs

None.

Related Issues or PRs

Dependencies Versions

No changes.

Notes on Testing

  1. Open a no-code model backed by BigQuery, run it. Logs panel should no longer flood with "Using Cached Object of bigquery_connection_object".
  2. Add a transformation (e.g. Sort) to a Postgres-backed model; the "Processing Model" line should show the actual model name (not empty quotes), and "Executing Model Node" should show `Materialization: TABLE` not `Materialization.TABLE`.
  3. After a successful run, the summary line should read `DONE PASS=N ...` with the correct non-zero count.
  4. Change the log-level selector to "All logs" and reload the page — selection should persist.
  5. Trigger an error; the row should appear in red when the selector is "Errors only".

Screenshots

No screenshots available — the log-level filter and severity-tinted rows require a WebSocket connection for live log streaming, which is not available in the React dev server proxy setup. The feature works in production where nginx handles WebSocket forwarding.

UI changes:

  • Log-level selector dropdown in the bottom Logs tab: All logs / Info & above / Warnings & errors / Errors only (persisted in localStorage)
  • Each log row is tinted by severity: grey for debug, default for info, amber for warnings, red for errors

Checklist

TBD

Checklist

I have read and understood the Contribution Guidelines.

Layer 1 — silence the worst offender
- Demote UsingCachedObject from InfoLevel to DebugLevel so the
  per-query "Using Cached Object of bigquery_connection_object" spam
  no longer reaches the UI at default verbosity.

Layer 2A — fix data bugs leaking dev internals into the UI
- ProcessingModel: avoid Processing Model : "" by using cls.__name__
  with file_name as a fallback, instead of str(cls) which can be empty
  for dynamically generated no-code model classes.
- ExecStatus / Materialization: stop str(Enum) from leaking the dotted
  enum names (ExecStatus.Success, Materialization.EPHEMERAL) into user
  messages; use .value so the UI shows SUCCESS / OK / TABLE.
- Summary counts: parse_and_fire_reports compared end_status against
  ExecStatus.Success/Error but end_status is set to OK/Fail, so
  pass/error counters stayed zero. Compare against the correct
  end-status values so DONE PASS=N now reflects reality.

Frontend
- Socket handler now captures the level alongside the message; each
  log entry is stored as { level, message } instead of a raw string.
- New log-level selector in the bottom logs tab:
    All logs / Info & above / Warnings & errors / Errors only
  Default is "Info & above" (hides debug noise out of the box).
  Choice persists in localStorage under visitran.logsLevel.
- Log rows are tinted by severity (grey/default/amber/red) for quick
  scanning when All is selected.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@abhizipstack abhizipstack requested review from a team as code owners April 15, 2026 06:28
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 15, 2026

Greptile Summary

This PR fixes several user-visible issues in the logs panel: enum repr leakage (ExecStatus.SuccessSUCCESS), the empty Processing Model : "" string, broken summary counters (PASS/ERROR now increment correctly), and per-query cache-object spam. A log-level filter with localStorage persistence and per-row severity tinting are added on the frontend.

  • warn_count and skip_count in parse_and_fire_reports are now correctly compared (.value instead of str()), but no code path in visitran.py sets end_status to "WARN" or "SKIPPED", so those two counters will still always be 0 in the DONE summary.

Confidence Score: 5/5

Safe to merge — all fixes are correct and the single finding is a pre-existing limitation, not a regression introduced by this PR.

All P1 bugs targeted by the PR are correctly fixed. The only comment is a P2 noting that warn/skip counters remain 0 because no code paths produce those end_status values, which is a pre-existing gap rather than a new regression. Frontend changes are well-structured with proper memoization and socket cleanup.

No files require special attention.

Important Files Changed

Filename Overview
backend/visitran/events/printer.py Fixed counter comparisons to use .value and elif chains; logic is correct, though no code path in visitran.py currently produces a "WARN" or "SKIPPED" end_status so those counters remain 0.
backend/visitran/events/types.py Single-line demotion of UsingCachedObject from InfoLevel to DebugLevel to suppress per-query cache spam from the UI. Change is correct and intentional.
backend/visitran/visitran.py Replaced all str(ExecStatus.X) usages with ExecStatus.X.value and fixed ProcessingModel class name lookup; all six call sites updated consistently.
frontend/src/ide/editor/no-code-model/no-code-model.jsx Added log-level Select filter with localStorage persistence, per-row severity tinting, useMemo for filteredLogs, and improved socket cleanup with explicit disconnect. Changes are well-structured.

Sequence Diagram

sequenceDiagram
    participant BE as Backend (visitran.py)
    participant EV as events/printer.py
    participant SK as WebSocket
    participant FE as NoCodeModel (JSX)

    BE->>BE: run node (success/fail)
    BE->>EV: BaseResult(end_status=ExecStatus.OK.value / Fail.value)
    BE->>EV: parse_and_fire_reports()
    EV->>EV: compare end_status against OK/Fail/Warn/Skipped .value
    EV->>SK: fire_event(SummaryReport, EndSummaryReportCounts)

    SK-->>FE: logs:{socketSessionId} { level, message }
    FE->>FE: setLogsInfo([...old, { level, message }])
    FE->>FE: filteredLogs = useMemo(filter by LOG_LEVEL_RANK[logsLevel])
    FE->>FE: render rows tinted by LOG_LEVEL_COLOR[el.level]

    note over FE: logsLevel persisted in localStorage (default: info)
Loading

Fix All in Claude Code

Prompt To Fix All With AI
This is a comment left during a code review.
Path: backend/visitran/events/printer.py
Line: 91-96

Comment:
**`warn_count` and `skip_count` will still always be zero**

The comparisons against `ExecStatus.Warn.value` ("WARN") and `ExecStatus.Skipped.value` ("SKIPPED") are now logically correct, but a grep of `visitran.py` shows that no code path ever sets `end_status` to either of those values — only `ExecStatus.OK.value` and `ExecStatus.Fail.value` are assigned. As a result, the DONE line will still always show `WARN=0 SKIP=0` regardless of what actually happened. This is a pre-existing gap that the counter fix doesn't fully close; if warn/skip paths are planned, the corresponding `end_status` assignments in `visitran.py` will need to be added.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (3): Last reviewed commit: "fix: use antd theme token for log-panel ..." | Re-trigger Greptile

Comment thread frontend/src/ide/editor/no-code-model/no-code-model.jsx Outdated
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@abhizipstack
Copy link
Copy Markdown
Contributor Author

Socket cleanup fix (d281ec8): The socket useEffect cleanup now properly calls newSocket.disconnect() to tear down the connection on unmount. Additionally, the listener is registered and unregistered using a closure-captured socketSessionId variable (assigned when the server sends session_id), ensuring the cleanup always references the correct session ID rather than the outer-scope cookie value.

@wicky-zipstack
Copy link
Copy Markdown
Contributor

wicky-zipstack commented Apr 16, 2026

LGTM overall

Copy link
Copy Markdown
Contributor

@Deepak-Gnanasekar Deepak-Gnanasekar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — APPROVED

Reviewed all 4 changed files (+94 / -43). Clean, targeted fixes with no new logic issues introduced.

Backend

printer.py — The root cause of PASS=0 WARN=0 ERROR=0 SKIP=0 TOTAL=0 was comparing end_status against ExecStatus.Success/ExecStatus.Error when it's actually set to OK/Fail. Fix is correct. The ifelif tightening is also appropriate since end_status values are mutually exclusive.

types.pyUsingCachedObject demotion from InfoLevel to DebugLevel is a clean one-liner. Users who need it can switch to "All logs" via the new dropdown.

visitran.py — All str(ExecStatus.X)ExecStatus.X.value replacements are consistent across all 5 call sites (models, tests, seeds, snapshots). The hasattr guard on node.materialization.value is a good defensive choice. getattr(cls, "__name__", "") or file_name correctly handles dynamic no-code model classes that lacked a meaningful __str__.

Frontend (no-code-model.jsx)

  • LOG_LEVEL_RANK / LOG_LEVEL_COLOR are correctly defined outside the component (no re-creation on render).
  • filteredLogs wrapped in useMemo with correct [logsInfo, logsLevel] deps.
  • localStorage persistence for log level is straightforward.
  • Socket cleanup fix is a genuine improvement: capturing socketSessionId via closure ensures cleanup targets the right listener, and newSocket.disconnect() properly tears down the connection on unmount. The old code referenced the outer-scope sessionId (cookie value) which could diverge from the server-assigned session.
  • dangerouslySetInnerHTML usage is pre-existing and parseLog sanitizes via DOMPurify — no new XSS surface.

Minor note (non-blocking)

  • If a log message arrives before the session_id event (unlikely but theoretically possible with race conditions), it would be silently dropped. Current behavior is fine since the socket listener is only registered after session_id fires anyway.

LGTM — safe to merge.

Copy link
Copy Markdown
Contributor

@tahierhussain tahierhussain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@abhizipstack Can you please add screenshots for the UI changes addressed in this PR?

Comment thread frontend/src/ide/editor/no-code-model/no-code-model.jsx Outdated
Replaced hardcoded #f0f0f0 border with token.colorBorderSecondary so
the log-level dropdown separator renders correctly in both light and
dark themes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@tahierhussain tahierhussain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@abhizipstack abhizipstack merged commit 3030f72 into main Apr 16, 2026
8 checks passed
@abhizipstack abhizipstack deleted the fix/logs-panel-noise-and-meaningful-messages branch April 16, 2026 11:36
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.

4 participants