← Back to PRs

#22139: Fix(ui): improve log formatting for JSON payloads

by npmisantosh open 2026-02-20 19:26 View on GitHub →
app: web-ui size: S
## Summary - **Problem:** JSONL logs often contain nested JSON strings or objects in keys "0", "1", and "2", which were previously rendered as flat, unreadable strings or generic `[object Object]` placeholders. - **Why it matters:** Developers could not effectively parse complex system event payloads (like heartbeat diagnostics or provider responses) without manually copying them out to a formatter. - **What changed:** Implemented a recursive JSON parser and formatter in the log controller to detect nested structures and pretty-print them with 2-space indentation; added max-height and overflow scrolling to log message containers. - **What did NOT change (scope boundary):** No changes were made to the server-side logging implementation or the WebSocket log-tailing protocol. ### Change Type (select all) - [ ] Bug fix - [x] Feature - [x] Refactor - [ ] Docs - [ ] Security hardening - [ ] Chore/infra ### Scope (select all touched areas) - [ ] Gateway / orchestration - [ ] Skills / tool execution - [ ] Auth / tokens - [ ] Memory / storage - [x] Integrations - [ ] API / contracts - [x] UI / DX - [ ] CI/CD / infra ### Linked Issue/PR - Closes # - Related # ### User-visible / Behavior Changes - **Logs Tab:** Nested JSON strings and objects are now automatically detected and pretty-printed. - **Logs Tab:** Subsystem detection is more robust, pulling from nested module or subsystem keys within the JSON payload. - **Logs Tab:** Long log entries (especially formatted JSON) now have a max-height of 300px and vertical scrollbars to maintain list usability. ### Security Impact (required) - New permissions/capabilities? (**No**) - Secrets/tokens handling changed? (**No**) - New/changed network calls? (**No**) - Command/tool execution surface changed? (**No**) - Data access scope changed? (**No**) ### Repro + Verification #### Environment - **OS:** Linux - **Runtime/container:** Node.js 22 - **Model/provider:** N/A (UI focused) #### Steps 1. Run the project: `npm start -- --port 3001`. 2. Navigate to the Logs tab. 3. Observe entries from subsystems like `gateway/heartbeat` or `diagnostic` which contain structured objects. #### Expected - JSON objects are indented and readable. - The UI remains responsive even with large log payloads. #### Actual - Structured logs are correctly parsed and pretty-printed. - Large logs are constrained to the 300px height limit. ### Evidence - [x] **Trace/log snippets:** Verified against `refer/openclaw-2026-02-20.log` structures. ### Human Verification (required) - **Verified scenarios:** Parsing of mixed string/JSON fields, recursive indentation, and scrollbar behavior for tall messages. - **Edge cases checked:** Invalid JSON strings (fallback to raw text), null/undefined fields, and very long single-line strings. - **What you did not verify:** Browser performance with >5,000 active DOM elements in the log list. ### Compatibility / Migration - Backward compatible? (**Yes**) - Config/env changes? (**No**) - Migration needed? (**No**) ### Failure Recovery (if this breaks) - **How to disable/revert:** Revert `ui/src/ui/controllers/logs.ts` to restore default string/object rendering. - **Known bad symptoms:** If a log line is extremely deep, the recursive formatter could theoretically hit a stack limit (though unlikely for these system logs). ### Risks and Mitigations - **Risk:** Heavily indented JSON might be cut off on small mobile screens. - **Mitigation:** The log message container allows horizontal scrolling if needed, and the overall app remains mobile-first. <!-- greptile_comment --> <h3>Greptile Summary</h3> Adds recursive JSON parsing and pretty-printing to the logs UI for better readability of nested payloads in keys "0", "1", and "2". Also adds max-height scrolling (300px) to long log messages. ## Key Changes - New `formatLogValue()` function recursively detects and formats nested JSON strings/objects with 2-space indentation - Enhanced subsystem detection to check nested `module` and `subsystem` keys - Changed message parsing to concatenate obj["1"] and obj["2"] instead of selecting just one - CSS: added `max-height: 300px` + `overflow-y: auto` to `.log-message` for vertical scrolling ## Issues Found - **Critical:** Infinite recursion risk in `formatLogValue()` (line 55) - no depth limit or circular reference protection when processing untrusted log data <h3>Confidence Score: 2/5</h3> - Has a critical infinite recursion vulnerability that could crash the UI - The recursive `formatLogValue()` function lacks depth limiting or circular reference protection, creating a crash risk when processing untrusted log data with deep nesting or circular structures. While the feature improves UX, the logic bug needs fixing before merge. - Pay close attention to `ui/src/ui/controllers/logs.ts` - the `formatLogValue()` function needs safeguards against infinite recursion <sub>Last reviewed commit: 92eb056</sub> <!-- greptile_other_comments_section --> <sub>(5/5) You can turn off certain types of comments like style [here](https://app.greptile.com/review/github)!</sub> <!-- /greptile_comment -->

Most Similar PRs