Skip to content

feat(logger): Custom console formatter for JSON and multiline strings#1442

Merged
afjcjsbx merged 2 commits intosipeed:mainfrom
afjcjsbx:feat/logger-stdout-formatting
Mar 14, 2026
Merged

feat(logger): Custom console formatter for JSON and multiline strings#1442
afjcjsbx merged 2 commits intosipeed:mainfrom
afjcjsbx:feat/logger-stdout-formatting

Conversation

@afjcjsbx
Copy link
Copy Markdown
Collaborator

@afjcjsbx afjcjsbx commented Mar 12, 2026

📝 Description

Implemented a custom FormatFieldValue function within the zerolog.ConsoleWriter.
This change intercepts and correctly formats multiline strings and complex JSON objects, which zerolog by default converts to byte arrays ([]byte) or escaped strings. This also fixes the issue where tool arguments in logs were being printed as raw byte arrays instead of readable JSON. The overall goal is to significantly improve Developer Experience (DX) and log readability during terminal debugging.

🗣️ Type of Change

  • 🐞 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 📖 Documentation update
  • ⚡ Code refactoring (no functional changes, no api changes)

🤖 AI Code Generation

  • 🤖 Fully AI-generated (100% AI, 0% Human)
  • 🛠️ Mostly AI-generated (AI draft, Human verified/modified)
  • 👨‍💻 Mostly Human-written (Human lead, AI assisted or none)

🔗 Related Issue

📚 Technical Context (Skip for Docs)

  • Reference URL:
  • Reasoning: By default, when zerolog logs structured fields or complex JSON to the ConsoleWriter, it serializes them into byte arrays or adds escape sequences. The new custom FormatFieldValue unquotes strings, restores actual line breaks in the terminal, and preserves the formatting of JSON blocks, making the stdout output much more human-readable. It specifically addresses the unreadable output of args in the ToolRegistry.ExecuteWithContext logs.

🧪 Test Environment

  • Hardware: - OS: - Model/Provider: N/A - Channels: N/A ## 📸 Evidence (Optional)
Click to view Logs/Screenshots

❌ BEFORE (Without Custom Formatter):
Newlines are printed as literal text, internal JSON is escaped, and tool arguments are printed as raw byte arrays.

18:51:09 DBG agent  loop.go:918 (agent.(*AgentLoop).runLLMIteration) > Full LLM request iteration=2 messages_json="[\n  [0] Role: system\n  Content: # picoclaw 🦞 (v0.2.2-nightly.20260312.6612ca09-10-gd18a319-dirty (git: d18a319b))\n\nYou are picoclaw, a helpful AI assistant.\n\n## Workspace\nYour workspace is at: /Users/afjcjsbx/.picoclaw/workspace\n...\n\n  [1] Role: user\n  Content: # Heartbeat Check\n\nCurrent time: 2026-03-12 18:51:06\n\nYou are a proactive AI assistant. This is a scheduled heartbeat check.\nReview the following tasks and execute any necessary actions using avail...\n\n  [2] Role: assistant\n  ToolCalls:\n    - ID: call_368487a7fbeb4e2ab6c096d7, Type: function, Name: read_file\n      Arguments: {\"path\":\"/Users/afjcjsbx/.picoclaw/workspace/memory/MEMORY.md\"}\n\n  [3] Role: tool\n  Content: [file: MEMORY.md | total: 398 bytes | read: bytes 0-397]\n[END OF FILE - no further content.]\n\n# Long-term Memory\n\nThis file stores important information that should persist across sessions.\n\n## Use...\n  ToolCallID: call_368487a7fbeb4e2ab6c096d7\n\n]" tools_json="[\n  [0] Type: function, Name: append_file\n      Description: Append content to the end of a file\n      Parameters: map[properties:map[content:map[description:The content to append type:string] path:map[description:The file path to append to type:string]] required:[path content] type:object]\n  [1] Type: function, Name: cron\n      Description: Schedule reminders, tasks, or system commands. IMPORTANT: When user asks to be reminded or scheduled, you MUST call this tool. Use 'at_seconds' for one-time reminders (e.g., 'remind me in 10 minutes' → at_seconds=600). Use 'every_seconds' ONLY for recurring tasks (e.g., 'every 2 hours' → every_seconds=7200). Use 'cron_expr' for complex recurring schedules. Use 'command' to execute shell commands directly.\n      Parameters: map[properties:map[action:map[description:Action to perform. Use 'add' when user wants to schedule a reminder or task. enum:[add list remove enable disable] type:string] at_seconds:map[description:...\n  [2] Type: function, Name: edit_file\n      Description: Edit a file by replacing old_text with new_text. The old_text must exist exactly in the file.\n 
115:52:06 INF tool   registry.go:168 (tools.(*ToolRegistry).ExecuteWithContext) > Tool execution started args=[123 34 110 101 120 116 84 104 111 117 103 104 116 78 101 101 100 101 100 34 58 102 97 108 115 101 44 34 116 104 111 117 103 104 116 34 58 34 83 105 110 116 101 115 105 32 102 105 110 97 108 101 32 101 32 114 97 99 99 111 109 97 110 100 97 122 105 111 110 105 58 32 76 97 32 115 116 114 97 116 101 103 105 97 32 83 119 105 110 103 32 84 114 97 100 105 110 103 32 84 114 101 110 100 32 70 111 108 108 111 119 105 110 103 32 99 111 110 32 105 110 100 105 99 97 116 111 114 105 32 116 101 99 110 105 99 105 32 195 168 32 108 97 32 112 105 195 185 32 114 101 97 108 105 115 116 105 99 97 32 112 101 114 32 114 97 103 103 105 117 110 103 101 114 101 32 117 110 32 116 97 114 103 101 116 32 100 105 32 36 53 48 45 56 48 47 103 105 111 114 110 111 32 40 112 105 195 185 32 114 101 97 108 105 115 116 105 99 111 32 100 101 108 32 116 97 114 103 101 116 32 111 114 105 103 105 110 97 108 101 32 100 105 32 36 49 48 48 47 103 105 111 114 110 111 41 46 32 67 111 110 32 117 110 32 99 97 112 105 116 97 108 101 32 100 105 32 36 49 48 46 48 48 48 45 49 53 46 48 48 48 44 32 112 111 115 115 111 32 102 97 114 101 32 50 45 51 32 116 114 97 100 101 115 47 103 105 111 114 110 111 32 99 111 110 32 112 111 115 105 122 105 111 110 105 32 100 105 32 36 51 48 48 45 52 48 48 44 32 116 97 114 103 101 116 32 100 105 32 112 114 111 102 105 116 116 111 32 100 101 108 32 50 45 51 37 32 40 36 54 45 49 50 32 112 101 114 32 116 114 97 100 101 41 44 32 101 32 103 101 115 116 105 111 110 101 32 100 101 108 32 114 105 115 99 104 105 111 32 114 105 103 111 114 111 115 97 32 100 101 108 32 50 37 32 112 101 114 32 116 114 97 100 101 46 32 73 108 32 114 101 110 100 105 109 101 110 116 111 32 97 110 110 117 111 32 116 97 114 103 101 116 32 115 97 114 101 98 98 101 32 36 49 56 46 48 48 48 45 50 57 46 48 48 48 32 40 49 50 48 45 50 48 48 37 32 97 110 110 117 111 41 44 32 99 104 101 32 195 168 32 101 115 116 114 101 109 97 109 101 110 116 101 32 97 109 98 105 122 105 111 115 111 32 109 97 32 112 111 115 115 105 98 105 108 101 32 99 111 110 32 97 122 105 111 110 105 32 118 111 108 97 116 105 108 105 32 40 81 81 81 44 32 78 86 68 65 41 46 32 195 136 32 102 111 110 100 97 109 101 110 116 97 108 101 32 105 110 105 122 105 97 114 101 32 99 111 110 32 97 99 99 111 117 110 116 32 100 101 109 111 44 32 105 109 112 97 114 97 114 101 32 103 114 97 100 117 97 108 109 101 110 116 101 44 32 101 32 109 97 110 116 101 110 101 114 101 32 108 97 32 100 105 115 99 105 112 108 105 110 97 32 101 32 108 97 32 103 101 115 116 105 111 110 101 32 100 101 108 32 114 105 115 99 104 105 111 46 32 76 97 32 114 105 115 112 111 115 116 97 32 102 105 110 97 108 101 32 100 111 118 114 101 98 98 101 32 101 115 115 101 114 101 32 109 111 108 116 111 32 100 101 116 116 97 103 108 105 97 116 97 32 101 32 116 114 97 115 112 97 114 101 110 116 101 32 115 117 105 32 114 105 115 99 104 105 46 34 44 34 116 104 111 117 103 104 116 78 117 109 98 101 114 34 58 49 56 44 34 116 111 116 97 108 84 104 111 117 103 104 116 115 34 58 49 56 125] tool=mcp_sequential-thinking_sequentialthinking

✅ AFTER (With Custom Formatter):
Strings break into new lines correctly, JSON objects retain their clean original characters, and tool arguments are fully readable.

18:51:09 DBG agent  loop.go:918 (agent.(*AgentLoop).runLLMIteration) > Full LLM request iteration=2 messages_json=
[
  [0] Role: system
  Content: # picoclaw 🦞 (v0.2.2-nightly.20260312.6612ca09-10-gd18a319-dirty (git: d18a319b))

You are picoclaw, a helpful AI assistant.
...
]

18:51:26 DBG agent  loop.go:918 (agent.(*AgentLoop).runLLMIteration) > Full LLM request iteration=1 messages_json=
[
  [0] Role: system
  Content: # picoclaw 🦞 (v0.2.2-nightly.20260312.6612ca09-10-gd18a319-dirty (git: d18a319b))
...
] tools_json=
[
  [0] Type: function, Name: append_file
      Description: Append content to the end of a file
...
]

☑️ Checklist

  • My code/docs follow the style of this project.
  • I have performed a self-review of my own changes.
  • I have updated the documentation accordingly.

@afjcjsbx afjcjsbx requested review from alexhoshina, lxowalle, mengzhuo and yinwm and removed request for lxowalle March 12, 2026 18:09
@sipeed-bot sipeed-bot Bot added type: enhancement New feature or request go Pull requests that update go code labels Mar 12, 2026
Comment thread pkg/logger/logger.go
})
}

func formatFieldValue(i any) string {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can you add a test against this function?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

hi @mengzhuo, test added, thank you! 🙏

@afjcjsbx afjcjsbx requested a review from mengzhuo March 13, 2026 13:18
xuwei-xy pushed a commit to xuwei-xy/picoclaw that referenced this pull request Mar 14, 2026
@afjcjsbx afjcjsbx merged commit 5a251b4 into sipeed:main Mar 14, 2026
4 checks passed
dj-oyu pushed a commit to dj-oyu/picoclaw that referenced this pull request Mar 16, 2026
…tting

feat(logger): Custom console formatter for JSON and multiline strings
j0904 pushed a commit to j0904/picoclaw that referenced this pull request Mar 22, 2026
…tting

feat(logger): Custom console formatter for JSON and multiline strings
andressg79 pushed a commit to andressg79/picoclaw that referenced this pull request Mar 30, 2026
…tting

feat(logger): Custom console formatter for JSON and multiline strings
ra1phdd pushed a commit to ra1phdd/picoclaw-pkg that referenced this pull request Apr 12, 2026
…tting

feat(logger): Custom console formatter for JSON and multiline strings
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

go Pull requests that update go code type: enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants