Skip to content

[duplicate-code] Duplicate Code Pattern: Log level dispatch quartet repeated across 3 logger façades #3687

@github-actions

Description

@github-actions

Part of duplicate code analysis: #3685

Summary

The LogInfo / LogWarn / LogError / LogDebug level-dispatch quartet appears three times in the logger package, once per logging façade (file, markdown, per-server). Each set of four functions follows the same structural pattern: a public one-liner that calls a private logWithXxx helper at the appropriate level constant.

Duplication Details

Pattern: 4-function level-dispatch quartet (×3 façades)

  • Severity: Medium
  • Occurrences: 3 complete sets (12 functions total)
  • Locations:
    • internal/logger/file_logger.go lines 122–140 — LogInfo / LogWarn / LogError / LogDebug calling logWithLevel
    • internal/logger/markdown_logger.go lines 197–214 — LogInfoMd / LogWarnMd / LogErrorMd / LogDebugMd calling logWithMarkdownLevel
    • internal/logger/server_file_logger.go lines 158–176 — LogInfoWithServer / LogWarnWithServer / LogErrorWithServer / LogDebugWithServer calling logWithLevelAndServer
  • Code Sample (shape is identical across all three files):
    // LogInfo logs an informational message
    func LogInfo(category, format string, args ...interface{}) {
        logWithLevel(LogLevelInfo, category, format, args...)
    }
    // LogWarn logs a warning message
    func LogWarn(category, format string, args ...interface{}) {
        logWithLevel(LogLevelWarn, category, format, args...)
    }
    // (LogError and LogDebug follow the same pattern)

Impact Analysis

  • Maintainability: Adding a new LogLevel constant requires updating the quartet in all three files. The existing logFuncs map (file_logger.go:147) partially mitigates this for the inner dispatch, but the public wrappers still need manual updates.
  • Bug Risk: Low for existing levels; medium for new level additions (easy to miss one façade).
  • Code Bloat: ~36 lines of structurally identical one-liner wrappers.

Refactoring Recommendations

  1. Code-generate the wrappers using go generate + a small template. Each façade provides only its inner logWithXxx function; the four public wrappers are emitted by generate. This is the highest-fidelity option if new levels are anticipated.

  2. Consolidate into a LogFacade struct with a single variadic Log(level, ...) method, replacing the four typed wrappers. Callers that currently rely on LogInfo(...) continue to work via thin aliases. This reduces the public surface while centralising level dispatch.

  3. Accept the pattern (lowest effort) — logFuncs already prevents switch-on-level duplication inside each helper; the remaining four wrappers per façade are very small. Document explicitly that adding a LogLevel requires updating all three façades.

Implementation Checklist

  • Review duplication findings
  • Decide on refactoring strategy (code-gen vs. LogFacade struct vs. document)
  • If refactoring: update all callers of the public log functions
  • Run make agent-finished to verify no regressions

Parent Issue

See parent analysis report: #3685
Related to #3685

Generated by Duplicate Code Detector · ● 1.6M ·

  • expires on Apr 20, 2026, 6:16 AM UTC

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions