Skip to content

[duplicate-code] Duplicate Code Pattern: Boilerplate initGlobal*/closeGlobal* Logger Wrappers #2909

@github-actions

Description

@github-actions

Part of duplicate code analysis: #2907

Summary

internal/logger/global_helpers.go contains 10 nearly-identical wrapper functions — 5 initGlobal* and 5 closeGlobal* pairs — one pair per logger type. Each wrapper is a 3-line delegation to the same generic initGlobalLogger / closeGlobalLogger helpers.

Duplication Details

Pattern: Repeated initGlobal* / closeGlobal* wrapper functions

  • Severity: Medium

  • Occurrences: 10 functions (5 pairs)

  • Location: internal/logger/global_helpers.go (lines ~120–168)

  • Code Sample (pattern repeats for all 5 logger types):

    func initGlobalFileLogger(logger *FileLogger) {
        initGlobalLogger(&globalLoggerMu, &globalFileLogger, logger)
    }
    func closeGlobalFileLogger() error {
        return closeGlobalLogger(&globalLoggerMu, &globalFileLogger)
    }
    
    func initGlobalJSONLLogger(logger *JSONLLogger) {
        initGlobalLogger(&globalJSONLMu, &globalJSONLLogger, logger)
    }
    func closeGlobalJSONLLogger() error {
        return closeGlobalLogger(&globalJSONLMu, &globalJSONLLogger)
    }
    // ... identical pattern for Markdown, ServerFile, Tools loggers

Impact Analysis

  • Maintainability: Adding a 6th logger type requires adding another pair of wrappers in the same pattern
  • Bug Risk: Low currently, but grows as more loggers are added
  • Code Bloat: ~40 lines of boilerplate; the real logic lives in 2 generic functions

Refactoring Recommendations

  1. Document the pattern explicitly — if the wrappers are intentional for type safety, add a comment explaining the design rationale so future contributors understand why the repetition exists.

  2. Use go:generate to produce wrapper functions from a template, so the single-source-of-truth lives in the template rather than in hand-written copies.

  3. Consider a logger registry for when a 6th logger type needs to be added:

    type globalLoggerEntry[T io.Closer] struct {
        mu     *sync.RWMutex
        logger *T
    }

    A registry approach scales without adding new wrapper pairs.

Implementation Checklist

  • Decide: document-as-intentional vs. generate vs. registry approach
  • Implement chosen approach
  • Verify existing callers are unaffected
  • Run make test to verify no regressions

Parent Issue

See parent analysis report: #2907
Related to #2907

Generated by Duplicate Code Detector ·

  • expires on Apr 7, 2026, 6:02 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