Skip to content

[duplicate-code] Duplicate Code Pattern: Verbose Error Logging Blocks #558

@github-actions

Description

@github-actions

🔍 Duplicate Code Pattern: Duplicated Error Logging Blocks

Part of duplicate code analysis: #555

Summary

Throughout the codebase, particularly in internal/launcher/launcher.go, there are multiple instances of verbose, multi-line log.Printf("[PREFIX]") blocks for error diagnostics and warnings. These blocks follow the same pattern of prefixing messages with [LAUNCHER], [DIFC], or other tags, resulting in significant code duplication.

Duplication Details

Pattern: Multi-line Prefixed Log Blocks

  • Severity: High
  • Occurrences: 50+ instances across the codebase
  • Primary Location: internal/launcher/launcher.go (30+ instances)
  • Secondary Locations: internal/server/unified.go, internal/difc/*.go, internal/cmd/root.go

Code Sample - Launcher Error Diagnostics

Example 1: Server Launch Failure (appears 2x in launcher.go)

// Lines 193-213 and 339-347
log.Printf("[LAUNCHER] ❌ FAILED to launch server '%s'", serverID)
log.Printf("[LAUNCHER] Error: %v", err)
log.Printf("[LAUNCHER] Debug Information:")
log.Printf("[LAUNCHER]   - Command: %s", serverCfg.Command)
log.Printf("[LAUNCHER]   - Args: %v", serverCfg.Args)
log.Printf("[LAUNCHER]   - Env vars: %v", sanitize.TruncateSecretMap(serverCfg.Env))
log.Printf("[LAUNCHER]   - Running in container: %v", l.runningInContainer)
log.Printf("[LAUNCHER]   - Is direct command: %v", isDirectCommand)
log.Printf("[LAUNCHER]   - Startup timeout: %v", l.startupTimeout)

Example 2: Security Warning (appears 2x in launcher.go)

// Lines 132-134 and 284-286
log.Printf("[LAUNCHER] ⚠️  WARNING: Server '%s' uses direct command execution inside a container", serverID)
log.Printf("[LAUNCHER] ⚠️  Security Notice: Command '%s' will execute with the same privileges as the gateway", serverCfg.Command)
log.Printf("[LAUNCHER] ⚠️  Consider using 'container' field instead for better isolation")

Example 3: Startup Commands (appears 2x in launcher.go)

// Lines 139-141 and 291-293
log.Printf("[LAUNCHER] Starting MCP server: %s", serverID)
log.Printf("[LAUNCHER] Command: %s", serverCfg.Command)
log.Printf("[LAUNCHER] Args: %v", sanitize.SanitizeArgs(serverCfg.Args))

Example 4: Timeout Error (appears 2x in launcher.go)

// Lines 228-230 and 366-368
log.Printf("[LAUNCHER] ❌ Server startup timed out after %v", l.startupTimeout)
log.Printf("[LAUNCHER] ⚠️  The server may be hanging or taking too long to initialize")
log.Printf("[LAUNCHER] ⚠️  Consider increasing 'startupTimeout' in gateway config if server needs more time")

Other Affected Areas

DIFC Logging in internal/server/unified.go:

// Multiple instances of DIFC prefix blocks
log.Printf("[DIFC] Agent %s | Secrecy: %v | Integrity: %v", agentID, ...)
log.Printf("[DIFC] Resource: %s | Operation: %s | Secrecy: %v | Integrity: %v", ...)
log.Printf("[DIFC] Access DENIED for agent %s to %s: %s", ...)

Agent Registry in internal/difc/agent.go:

// Multiple instances of DIFC tag logging
log.Printf("[DIFC] Agent %s gained secrecy tag: %s", a.AgentID, tag)
log.Printf("[DIFC] Agent %s gained integrity tag: %s", a.AgentID, tag)
log.Printf("[DIFC] Agent %s accumulated secrecy tags from read: %v", ...)

Impact Analysis

  • Maintainability: When log format changes are needed (e.g., JSON logging, structured logging), updates are required in 50+ locations
  • Code Bloat: Verbose multi-line blocks make functions significantly longer and harder to read
  • Inconsistency Risk: Different developers may format similar log messages differently
  • Testing Overhead: Each log block is difficult to mock or test independently
  • Performance: Multiple log.Printf calls have overhead compared to single structured log call

Refactoring Recommendations

1. Create Structured Logging Helpers in launcher package

Extract common logging patterns into helper methods:

// internal/launcher/log_helpers.go

// logLaunchStart logs server launch initiation
func (l *Launcher) logLaunchStart(serverID string, cfg *config.ServerConfig, sessionID string) {
    if sessionID != "" {
        log.Printf("[LAUNCHER] Starting MCP server for session: %s (session: %s)", serverID, sessionID)
    } else {
        log.Printf("[LAUNCHER] Starting MCP server: %s", serverID)
    }
    log.Printf("[LAUNCHER] Command: %s", cfg.Command)
    log.Printf("[LAUNCHER] Args: %v", sanitize.SanitizeArgs(cfg.Args))
}

// logLaunchError logs detailed launch failure diagnostics
func (l *Launcher) logLaunchError(serverID, sessionID string, err error, cfg *config.ServerConfig, isDirectCommand bool) {
    log.Printf("[LAUNCHER] ❌ FAILED to launch server '%s'%s", serverID, sessionSuffix(sessionID))
    log.Printf("[LAUNCHER] Error: %v", err)
    log.Printf("[LAUNCHER] Debug Information:")
    log.Printf("[LAUNCHER]   - Command: %s", cfg.Command)
    log.Printf("[LAUNCHER]   - Args: %v", cfg.Args)
    log.Printf("[LAUNCHER]   - Env vars: %v", sanitize.TruncateSecretMap(cfg.Env))
    log.Printf("[LAUNCHER]   - Running in container: %v", l.runningInContainer)
    log.Printf("[LAUNCHER]   - Is direct command: %v", isDirectCommand)
    log.Printf("[LAUNCHER]   - Startup timeout: %v", l.startupTimeout)
    
    l.logPossibleCauses(isDirectCommand, cfg.Command)
}

// logSecurityWarning logs container security warnings
func (l *Launcher) logSecurityWarning(serverID string, command string) {
    log.Printf("[LAUNCHER] ⚠️  WARNING: Server '%s' uses direct command execution inside a container", serverID)
    log.Printf("[LAUNCHER] ⚠️  Security Notice: Command '%s' will execute with the same privileges as the gateway", command)
    log.Printf("[LAUNCHER] ⚠️  Consider using 'container' field instead for better isolation")
}

// logTimeoutError logs startup timeout diagnostics
func (l *Launcher) logTimeoutError() {
    log.Printf("[LAUNCHER] ❌ Server startup timed out after %v", l.startupTimeout)
    log.Printf("[LAUNCHER] ⚠️  The server may be hanging or taking too long to initialize")
    log.Printf("[LAUNCHER] ⚠️  Consider increasing 'startupTimeout' in gateway config if server needs more time")
}

func sessionSuffix(sessionID string) string {
    if sessionID == "" {
        return ""
    }
    return fmt.Sprintf(" for session '%s'", sessionID)
}

Usage:

// Before:
log.Printf("[LAUNCHER] Starting MCP server: %s", serverID)
log.Printf("[LAUNCHER] Command: %s", serverCfg.Command)
log.Printf("[LAUNCHER] Args: %v", sanitize.SanitizeArgs(serverCfg.Args))

// After:
l.logLaunchStart(serverID, serverCfg, "")

Estimated effort: 2-3 hours
Benefits:

  • Single source of truth for log message format
  • Easier to add structured logging later
  • Cleaner, more readable launch functions
  • Consistent error diagnostics across all launch paths

2. Consider Structured Logging (Future Enhancement)

Instead of formatted strings, use structured fields:

import "log/slog"

// Example structured logging (future work)
slog.Error("server launch failed",
    "server_id", serverID,
    "command", cfg.Command,
    "error", err,
    "in_container", l.runningInContainer,
    "timeout", l.startupTimeout,
)

Estimated effort: 4-6 hours (major refactor)
Benefits:

  • Machine-parseable logs
  • Better integration with log aggregation tools
  • Easier filtering and searching
  • Better performance (single log call)

3. Extract DIFC Logging Helpers

Similar pattern for internal/difc and internal/server/unified.go:

// internal/difc/log_helpers.go

func logAgentState(agentID string, secrecy, integrity []Tag) {
    log.Printf("[DIFC] Agent %s | Secrecy: %v | Integrity: %v", agentID, secrecy, integrity)
}

func logResourceAccess(agentID, resource, operation string, allowed bool, reason string) {
    if allowed {
        log.Printf("[DIFC] Access ALLOWED for agent %s to %s", agentID, resource)
    } else {
        log.Printf("[DIFC] Access DENIED for agent %s to %s: %s", agentID, resource, reason)
    }
}

Estimated effort: 1-2 hours
Benefits:

  • Consistent DIFC logging format
  • Easier to add audit logging later

Implementation Checklist

  • Review logging helper approach with team
  • Create internal/launcher/log_helpers.go
  • Implement launcher logging helper methods
  • Refactor GetOrLaunch to use helpers
  • Refactor GetOrLaunchForSession to use helpers
  • (Optional) Create DIFC logging helpers
  • (Optional) Create unified server logging helpers
  • Update unit tests if needed
  • Run make agent-finished to verify no regressions
  • Document logging helper usage in AGENTS.md

Parent Issue

See parent analysis report: #555
Related to #555

AI generated by Duplicate Code Detector

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions