Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions internal/logger/global_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,9 @@ import (
// - Error: Returns nil (never fails, falls back to unified logging)
// - Use case: Per-server logs are helpful but not required
//
// Note: ServerFileLogger doesn't use initLogger() because it creates
// files on-demand, but follows the same fallback philosophy.
// Note: ServerFileLogger uses serverFileLoggerFactory but not initLogger()
// because it creates per-serverID files on demand rather than opening
// a single file at initialization. The factory setup receives a nil file.
//
// Global Logger Management:
//
Expand Down
35 changes: 23 additions & 12 deletions internal/logger/server_file_logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"log"
"os"
"path/filepath"
"sync"

"github.com/github/gh-aw-mcpg/internal/syncutil"
Expand All @@ -24,6 +23,20 @@ var (
globalServerLoggerMu sync.RWMutex
)

// serverFileLoggerFactory bundles the setup and error-handler for ServerFileLogger.
// Unlike other factories, setup receives a nil file because ServerFileLogger creates
// per-serverID files on demand rather than opening a single file at initialization.
var serverFileLoggerFactory = loggerFactory[*ServerFileLogger]{
setup: func(_ *os.File, logDir, _ string) (*ServerFileLogger, error) {
log.Printf("Initialized per-serverID logging in directory: %s", logDir)
return newServerFileLogger(logDir, false), nil
},
onError: func(err error, logDir, _ string) (*ServerFileLogger, error) {
return fallbackLoggerOnInitError(err, "Failed to create log directory for server logs",
"Falling back to unified logging only", newServerFileLogger(logDir, true))
},
}

func newServerFileLogger(logDir string, useFallback bool) *ServerFileLogger {
return &ServerFileLogger{
logDir: logDir,
Expand All @@ -35,17 +48,16 @@ func newServerFileLogger(logDir string, useFallback bool) *ServerFileLogger {

// InitServerFileLogger initializes the global server file logger
func InitServerFileLogger(logDir string) error {
// Create log directory if it doesn't exist
var sfl *ServerFileLogger
var initErr error
if err := os.MkdirAll(logDir, 0755); err != nil {
logFallbackWarnings(err, "Failed to create log directory for server logs", "Falling back to unified logging only")
sfl := newServerFileLogger(logDir, true)
initGlobalLogger(&globalServerLoggerMu, &globalServerFileLogger, sfl)
return nil
sfl, initErr = serverFileLoggerFactory.onError(err, logDir, "")
} else {
sfl, initErr = serverFileLoggerFactory.setup(nil, logDir, "")
}
if initErr != nil {
return initErr
}

sfl := newServerFileLogger(logDir, false)

log.Printf("Initialized per-serverID logging in directory: %s", logDir)
initGlobalLogger(&globalServerLoggerMu, &globalServerFileLogger, sfl)
return nil
}
Expand All @@ -60,8 +72,7 @@ func (sfl *ServerFileLogger) getOrCreateLogger(serverID string) (*log.Logger, er

// Create log file for this serverID
fileName := fmt.Sprintf("%s.log", serverID)
logPath := filepath.Join(sfl.logDir, fileName)
file, err := os.OpenFile(logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
file, err := initLogFile(sfl.logDir, fileName, os.O_APPEND)
if err != nil {
return nil, fmt.Errorf("failed to open log file for server %s: %w", serverID, err)
}
Expand Down
Loading