Files
unraid-docker-manager/.planning/phases/04-logs/04-01-PLAN.md
T
Lucas Berger 21e888c1ce docs: remove NLU from v1.0 scope
- Remove Claude API integration and intent parsing (04-02-PLAN)
- REQ-08 (conversational queries) moved to out of scope
- Phase 4 renamed from "Logs & Intelligence" to "Logs" (complete)
- v1.0 now focuses on keyword-based container control

Simple substring matching works well for container management.
NLU adds complexity without proportional value for v1.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 14:52:37 -05:00

199 lines
6.6 KiB
Markdown

---
phase: 04-logs-intelligence
plan: 01
type: execute
wave: 1
depends_on: []
files_modified: [n8n-workflow.json]
autonomous: true
user_setup:
- service: anthropic
why: "Claude API for natural language understanding"
env_vars:
- name: ANTHROPIC_API_KEY
source: "Anthropic Console -> API Keys -> Create Key"
dashboard_config: []
must_haves:
truths:
- "User can request logs for a container by name"
- "User can specify number of log lines (default 50)"
- "Logs are returned in readable format in Telegram"
artifacts:
- path: "n8n-workflow.json"
provides: "Logs command routing and Docker API integration"
contains: "logs"
key_links:
- from: "Switch node"
to: "Docker logs API call"
via: "logs command pattern match"
pattern: "logs|show logs"
- from: "Docker API response"
to: "Telegram reply"
via: "log formatting code node"
---
<objective>
Implement container log retrieval via Telegram commands.
Purpose: Delivers REQ-07 (view logs with configurable line count) - users can troubleshoot containers directly from their phone by viewing recent logs.
Output: Extended n8n workflow with logs command routing, Docker logs API call, and formatted log response.
</objective>
<execution_context>
@/home/luc/.claude/get-shit-done/workflows/execute-plan.md
@/home/luc/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/04-logs-intelligence/04-RESEARCH.md
@.planning/phases/02-docker-integration/02-02-SUMMARY.md
@n8n-workflow.json
</context>
<tasks>
<task type="auto">
<name>Task 1: Add logs command routing to workflow</name>
<files>n8n-workflow.json</files>
<action>
Extend the main Switch node to detect logs commands. Pattern: "logs <container>" or "show logs <container>" with optional line count.
Add new route in Switch node:
- Condition: message matches /^(show\s+)?logs\s+/i
- Route to new "Parse Logs Command" Code node
Create "Parse Logs Command" Code node:
- Extract container name from message
- Extract line count if specified (e.g., "logs plex 100"), default to 50
- Return: { container: string, lines: number }
Example inputs to handle:
- "logs plex" -> { container: "plex", lines: 50 }
- "show logs sonarr" -> { container: "sonarr", lines: 50 }
- "logs nginx 100" -> { container: "nginx", lines: 100 }
- "show logs radarr last 200" -> { container: "radarr", lines: 200 }
</action>
<verify>
In n8n workflow editor, send message "logs test" - should route to Parse Logs Command node (visible in execution view). Check output includes container and lines fields.
</verify>
<done>Logs commands route to dedicated branch with parsed container name and line count.</done>
</task>
<task type="auto">
<name>Task 2: Implement Docker logs API call with formatting</name>
<files>n8n-workflow.json</files>
<action>
After Parse Logs Command, add container matching (reuse existing fuzzy match pattern from actions branch).
Create "Build Logs Command" Code node:
- Input: matched container ID and requested line count
- Build curl command:
```
curl -s --unix-socket /var/run/docker.sock "http://localhost/v1.53/containers/CONTAINER_ID/logs?stdout=1&stderr=1&tail=LINES&timestamps=1"
```
- Note: Docker logs API returns binary stream with 8-byte header per line. First byte indicates stream (1=stdout, 2=stderr).
Create "Execute Logs" Execute Command node:
- Run the curl command
Create "Format Logs" Code node:
- Parse Docker log stream format (strip 8-byte headers from each line)
- Format for Telegram:
- Truncate if > 4000 chars (Telegram message limit)
- Add header: "Logs for <container> (last N lines):"
- Use monospace formatting with <pre> tags (HTML parse mode already enabled)
- Handle empty logs gracefully: "No logs available for <container>"
- Handle errors: "Could not retrieve logs for <container>: <error>"
Wire to Telegram Send Message node for reply.
</action>
<verify>
Test via Telegram:
1. "logs n8n" - should return recent n8n container logs in monospace format
2. "logs n8n 10" - should return only 10 lines
3. "logs nonexistent" - should return friendly "no container found" message
</verify>
<done>Users can retrieve container logs via Telegram with configurable line count, formatted for readability.</done>
</task>
<task type="auto">
<name>Task 3: Handle Docker log stream binary format</name>
<files>n8n-workflow.json</files>
<action>
The Docker logs API returns a multiplexed stream with 8-byte headers. Each frame:
- Byte 0: stream type (1=stdout, 2=stderr)
- Bytes 1-3: reserved (zeros)
- Bytes 4-7: frame size (big-endian uint32)
- Remaining bytes: log content
Update "Format Logs" Code node to properly decode this:
```javascript
// Docker logs binary stream decoder
const rawOutput = $input.item.json.stdout || '';
// Docker API with timestamps returns text lines when using tail parameter
// But may have 8-byte binary headers we need to strip
const lines = rawOutput.split('\n')
.filter(line => line.length > 0)
.map(line => {
// Check if line starts with binary header (non-printable chars in first 8 bytes)
if (line.length > 8 && line.charCodeAt(0) <= 2) {
return line.substring(8);
}
return line;
})
.join('\n');
// Truncate for Telegram (4096 char limit, leave room for header)
const maxLen = 3800;
const truncated = lines.length > maxLen
? lines.substring(0, maxLen) + '\n... (truncated)'
: lines;
return {
formatted: truncated,
lineCount: lines.split('\n').length
};
```
Add error indicator prefix for stderr lines if desired (optional enhancement).
</action>
<verify>
Test with a container known to have logs:
1. Send "logs n8n 20" via Telegram
2. Verify output is readable text (no garbled binary characters)
3. Verify timestamps appear if container outputs them
</verify>
<done>Docker log binary stream format properly decoded into readable text.</done>
</task>
</tasks>
<verification>
After all tasks:
1. Send "logs n8n" - returns formatted logs
2. Send "logs plex 100" - returns up to 100 lines
3. Send "show logs sonarr" - alternative syntax works
4. Send "logs nonexistent" - friendly error message
5. Logs display in monospace (preformatted) in Telegram
</verification>
<success_criteria>
- REQ-07 delivered: Users can view container logs with configurable line count
- Default 50 lines when not specified
- Multiple syntax variations supported (logs X, show logs X)
- Binary stream format properly decoded
- Output formatted for Telegram readability (monospace, truncated if needed)
</success_criteria>
<output>
After completion, create `.planning/phases/04-logs-intelligence/04-01-SUMMARY.md`
</output>