Files
2026-02-08 18:56:44 -05:00

12 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, must_haves
phase plan type wave depends_on files_modified autonomous must_haves
10.2-better-logging-and-log-management 01 execute 1
n8n-workflow.json
true
truths artifacts key_links
Error ring buffer stores up to 50 structured error entries in workflow static data
/errors command returns recent errors in human-readable format via Telegram
/clear-errors command resets the error ring buffer
/debug on|off|status toggles debug mode stored in static data
/trace <correlationId> returns all entries matching a correlation ID
Hidden commands are NOT listed in /start help menu
path provides contains
n8n-workflow.json Error ring buffer infrastructure, debug toggle, hidden command routing and responses Process Debug Command
from to via pattern
Keyword Router Process Debug Command switch output for /errors, /clear-errors, /debug, /trace keywords keyword-errors|keyword-debug|keyword-trace|keyword-clear-errors
from to via pattern
Process Debug Command Send Debug Response formatted message output chatId.*text
Build the error ring buffer foundation and hidden Telegram debug commands in the main workflow.

Purpose: Establish the centralized error/trace storage infrastructure (workflow static data with ring buffer) and the hidden command interface (/errors, /clear-errors, /debug, /trace) that Claude and the user can use for quick diagnostics. This is the foundation that Plans 02 and 03 build upon.

Output: Modified n8n-workflow.json with ring buffer initialization, hidden command routing, and Telegram response nodes for all 4 debug commands.

<execution_context> @/home/luc/.claude/get-shit-done/workflows/execute-plan.md @/home/luc/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/STATE.md @.planning/ROADMAP.md @n8n-workflow.json @DEPLOY-SUBWORKFLOWS.md @.planning/phases/10.2-better-logging-and-log-management/10.2-CONTEXT.md @.planning/phases/10.2-better-logging-and-log-management/10.2-RESEARCH.md Task 1: Add hidden command routing to Keyword Router and create debug command processor n8n-workflow.json Modify the Keyword Router switch node (id: `switch-keyword-router`) to add 4 new keyword outputs BEFORE the fallback output. The new outputs must use `startsWith` operator (not `contains`) to avoid false matches with regular text:
  1. keyword-errors: matches /errors (startsWith, case-insensitive) -> outputKey: "errors"
  2. keyword-clear-errors: matches /clear (startsWith, case-insensitive) -> outputKey: "clear-errors"
  3. keyword-debug: matches /debug (startsWith, case-insensitive) -> outputKey: "debug"
  4. keyword-trace: matches /trace (startsWith, case-insensitive) -> outputKey: "trace"

All 4 outputs route to a single new Code node: Process Debug Command (id: code-process-debug-command).

The Process Debug Command Code node implements ALL 4 commands in a single code block. It reads $json.message.text to determine which command was invoked, then:

Static data structure (initialize if missing):

const staticData = $getWorkflowStaticData('global');
if (!staticData.errorLog) {
  staticData.errorLog = {
    debug: { enabled: false, executionCount: 0 },
    errors: { buffer: [], nextId: 1, count: 0, lastCleared: new Date().toISOString() },
    traces: { buffer: [], nextId: 1 }
  };
}

Command handling:

  • /errors [N]: Read staticData.errorLog.errors.buffer, take last N entries (default 5, max 50), format each as:

    #{id} - {timestamp}
    Workflow: {workflow} > {node}
    {userMessage}
    HTTP: {httpCode} (if present)
    

    If no errors, return "No errors recorded." Include total error count and debug mode status at bottom.

  • /clear-errors: Reset staticData.errorLog.errors.buffer = [], reset nextId = 1, update lastCleared. Return "Error log cleared. {count} entries removed."

  • /debug on|off|status:

    • on: Set staticData.errorLog.debug.enabled = true, reset executionCount = 0. Return "Debug mode enabled. Tracing sub-workflow boundaries and callback routing."
    • off: Set staticData.errorLog.debug.enabled = false. Return "Debug mode disabled."
    • status (or no argument): Return debug mode state, execution count, error buffer size, trace buffer size.
  • /trace <correlationId>: Search both staticData.errorLog.errors.buffer and staticData.errorLog.traces.buffer for entries matching the correlationId. Format results chronologically. If no matches, return "No entries found for correlation ID: {id}".

The Code node returns { json: { chatId, text } } where chatId comes from $json.message.chat.id and text is the formatted response (use HTML parse mode with <pre> for structured output).

Wire the output of Process Debug Command to a new Telegram node: Send Debug Response (id: telegram-send-debug-response), which sends the message using chatId and text from the Code node output, with parse_mode: HTML. Use the standard Telegram credential (id: I0xTTiASl7C1NZhJ, name: "Telegram account").

Positioning: Place Process Debug Command at position [1120, -200] and Send Debug Response at [1340, -200] to keep them visually grouped above the existing menu path.

Important: Do NOT modify the Show Menu text or /start command response. These debug commands must remain hidden/unlisted.

Node count impact: +2 new nodes (Code + Telegram send). - Parse n8n-workflow.json with python3 -c "import json; ..." to verify: 1. Keyword Router has 4 new switch rules (errors, clear-errors, debug, trace) 2. Process Debug Command node exists with type n8n-nodes-base.code 3. Send Debug Response node exists with type n8n-nodes-base.telegram 4. Connections exist: Keyword Router -> Process Debug Command -> Send Debug Response 5. Total node count is 170 (168 + 2 new nodes) - Verify the Code node's jsCode contains $getWorkflowStaticData('global') and handles all 4 commands Keyword Router routes /errors, /clear-errors, /debug, /trace to Process Debug Command. The code node initializes static data structure, implements all 4 commands, and outputs formatted text. Send Debug Response delivers the message via Telegram. No changes to existing Show Menu text.

Task 2: Add error logging utility function and ring buffer write helper n8n-workflow.json Create a new Code node: **Log Error** (id: `code-log-error`) that serves as the centralized error logging entry point. This node will be called from multiple places in the main workflow (wired in Plan 02).

The Log Error node expects input with these fields:

  • correlationId (string, optional - falls back to execution ID)
  • workflow (string - "main" or sub-workflow name like "n8n-actions")
  • node (string - node that encountered the error)
  • operation (string - what was being done, e.g., "docker.stop")
  • userMessage (string - user-friendly error summary)
  • errorMessage (string - technical error message)
  • errorStack (string, optional - stack trace)
  • httpCode (number, optional - HTTP status code)
  • rawResponse (string, optional - raw API response, will be truncated)
  • contextData (object, optional - additional context like containerId, subWorkflowInput/Output)
  • chatId (number - for pass-through to downstream)
  • text (string, optional - for pass-through to downstream)

Implementation:

const staticData = $getWorkflowStaticData('global');
const input = $input.item.json;

// Initialize if needed
if (!staticData.errorLog) {
  staticData.errorLog = {
    debug: { enabled: false, executionCount: 0 },
    errors: { buffer: [], nextId: 1, count: 0, lastCleared: new Date().toISOString() },
    traces: { buffer: [], nextId: 1 }
  };
}

const MAX_ERRORS = 50;
const errorEntry = {
  id: `err_${String(staticData.errorLog.errors.nextId).padStart(3, '0')}`,
  correlationId: input.correlationId || $execution.id,
  timestamp: new Date().toISOString(),
  executionId: $execution.id,
  workflow: input.workflow || 'main',
  node: input.node || 'unknown',
  operation: input.operation || 'unknown',
  userMessage: input.userMessage || input.errorMessage || 'Unknown error',
  error: {
    message: input.errorMessage || 'Unknown error',
    stack: (input.errorStack || '').substring(0, 500),
    httpCode: input.httpCode || null,
    rawResponse: (input.rawResponse || '').substring(0, 1000)
  },
  context: input.contextData || {}
};

// Ring buffer: push and rotate
staticData.errorLog.errors.buffer.push(errorEntry);
if (staticData.errorLog.errors.buffer.length > MAX_ERRORS) {
  staticData.errorLog.errors.buffer.shift();
}
staticData.errorLog.errors.nextId++;
staticData.errorLog.errors.count++;

// Pass through all input data so downstream nodes still work
return { json: { ...input, _errorLogged: true, _errorId: errorEntry.id } };

Positioning: Place Log Error at position [2600, -200] (utility area, visually separate from main flow).

Also create a Log Trace Code node (id: code-log-trace) for debug-mode trace entries. This node:

  • Checks staticData.errorLog.debug.enabled first; if false, passes data through unchanged
  • If debug is enabled, increments executionCount and checks auto-disable at 100
  • Stores trace entry in staticData.errorLog.traces.buffer (ring buffer, max 50)
  • Trace entry fields: id, correlationId, timestamp, executionId, event (string: "sub-workflow-call" | "callback-routing"), workflow, node, data (object with input/output/duration or callbackData/routeTaken)
  • Passes through all input data unchanged

Positioning: Place Log Trace at position [2600, -400].

These two nodes are NOT connected to anything yet -- they will be wired in Plan 02. They are standalone utility Code nodes that Plan 02 and Plan 03 will reference.

Node count impact: +2 new nodes (total now 172 including Task 1's additions). - Parse n8n-workflow.json to verify: 1. Log Error node exists (id: code-log-error) with type n8n-nodes-base.code 2. Log Trace node exists (id: code-log-trace) with type n8n-nodes-base.code 3. Log Error's jsCode contains $getWorkflowStaticData, MAX_ERRORS = 50, buffer.push, buffer.shift 4. Log Trace's jsCode contains debug.enabled check and auto-disable at 100 5. Total node count is 172 6. Both nodes have no incoming or outgoing connections (standalone) Log Error and Log Trace utility nodes exist in the main workflow with correct ring buffer logic, field truncation, and auto-disable. They are ready to be wired by Plan 02 and Plan 03.

1. `python3 -c "import json; wf=json.load(open('n8n-workflow.json')); print(len(wf['nodes']))"` returns 172 2. Keyword Router has outputs for errors, clear-errors, debug, trace 3. All 4 hidden commands handled in Process Debug Command code 4. Log Error and Log Trace utility nodes exist and are unconnected 5. No changes to Show Menu text (commands remain hidden) 6. All new nodes use correct n8n typeVersion and credential references

<success_criteria>

  • Main workflow has 172 nodes (168 + 4 new)
  • Ring buffer infrastructure initialized in workflow static data
  • /errors, /clear-errors, /debug, /trace commands routed and handled
  • Log Error and Log Trace utility nodes ready for wiring
  • No regression to existing functionality </success_criteria>
After completion, create `.planning/phases/10.2-better-logging-and-log-management/10.2-01-SUMMARY.md`