-
Notifications
You must be signed in to change notification settings - Fork 3
Description
🔍 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.Printfcalls 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
GetOrLaunchto use helpers - Refactor
GetOrLaunchForSessionto use helpers - (Optional) Create DIFC logging helpers
- (Optional) Create unified server logging helpers
- Update unit tests if needed
- Run
make agent-finishedto 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