-
Notifications
You must be signed in to change notification settings - Fork 16
Description
Part of duplicate code analysis: #1882
Summary
The [TIMESTAMP] [LEVEL] [CATEGORY] MESSAGE log-line formatting block is copy-pasted verbatim in at least 3 logger files. A single-character format change (e.g., switching from RFC3339 to RFC3339Nano) requires editing multiple files.
Duplication Details
Pattern: Inline Log-Line Timestamp Construction
- Severity: Medium
- Occurrences: 5 instances across 3+ logger files
- Locations:
internal/logger/file_logger.go(lines ~85–89)internal/logger/server_file_logger.go(lines ~111–115)internal/logger/markdown_logger.go(similar block)
Exact duplicate (file_logger.go and server_file_logger.go are byte-for-byte identical for these 4 lines):
timestamp := time.Now().UTC().Format(time.RFC3339)
message := fmt.Sprintf(format, args...)
logLine := fmt.Sprintf("[%s] [%s] [%s] %s", timestamp, level, category, message)
fl.logger.Println(logLine) // server_file_logger: logger.Println(logLine)Impact Analysis
- Maintainability: Format changes (timestamp precision, bracket style, JSON output) require multi-file edits
- Bug Risk: Low for now, but any drift (e.g., one file switching to UTC+local or adding a request-ID field) will silently produce inconsistent log formats
- Code Bloat: ~20–30 lines of duplicated formatting logic (small but exact)
Refactoring Recommendations
-
Extract
FormatLogLineutility (quick win, ~30 min effort):// internal/logger/format.go func FormatLogLine(level, category, format string, args ...any) string { timestamp := time.Now().UTC().Format(time.RFC3339) message := fmt.Sprintf(format, args...) return fmt.Sprintf("[%s] [%s] [%s] %s", timestamp, level, category, message) }
Each logger's write path becomes:
fl.logger.Println(FormatLogLine(level, category, format, args...))
-
Consider
timeutilpackage —internal/timeutil/already exists;FormatLogLineor at minimumFormatTimestamp()could live there to avoid circular imports. -
Single source of truth for log format — store the format string as a package-level constant so it can be changed in one place.
Implementation Checklist
- Create
internal/logger/format.gowithFormatLogLinehelper - Replace inline blocks in
file_logger.go,server_file_logger.go,markdown_logger.go - Run
make testto verify no output format regressions - Check if any tests assert on exact log-line format and update them
Parent Issue
See parent analysis report: #1882
Related to #1882
Generated by Duplicate Code Detector · ◷
- expires on Mar 21, 2026, 2:57 AM UTC