package logger import ( "log/slog" "os" "path" "strings" "git.benadis.ru/gitops/benadis-rac/internal/constants" ) // Logger интерфейс для логирования type Logger interface { Debug(msg string, args ...any) Info(msg string, args ...any) Warn(msg string, args ...any) Error(msg string, args ...any) DebugCommand(msg string, command []string) } // SlogLogger реализация Logger с использованием slog type SlogLogger struct { logger *slog.Logger } // NewLogger создает новый логгер func NewLogger(level string) Logger { var logLevel slog.Level switch strings.ToLower(level) { case "debug": logLevel = slog.LevelDebug case "info": logLevel = slog.LevelInfo case "warn": logLevel = slog.LevelWarn case "error": logLevel = slog.LevelError default: logLevel = slog.LevelInfo } l := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ AddSource: true, Level: logLevel, ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr { if a.Key == slog.SourceKey { s := a.Value.Any().(*slog.Source) s.File = path.Base(s.File) } return a }, })) l = l.With(slog.Group("App info", slog.String("version", constants.AppVersion), )) return &SlogLogger{logger: l} } // Debug логирует отладочное сообщение func (l *SlogLogger) Debug(msg string, args ...any) { l.logger.Debug(msg, args...) } // Info логирует информационное сообщение func (l *SlogLogger) Info(msg string, args ...any) { l.logger.Info(msg, args...) } // Warn логирует предупреждение func (l *SlogLogger) Warn(msg string, args ...any) { l.logger.Warn(msg, args...) } // Error логирует ошибку func (l *SlogLogger) Error(msg string, args ...any) { l.logger.Error(msg, args...) } // DebugCommand логирует команду с маскированием паролей func (l *SlogLogger) DebugCommand(msg string, command []string) { maskedCommand := maskPasswords(command) l.logger.Debug(msg, "command", strings.Join(maskedCommand, " ")) } // maskPasswords маскирует пароли в команде func maskPasswords(command []string) []string { masked := make([]string, len(command)) copy(masked, command) // Преобразуем строку флагов в массив passwordFlags := strings.Split(constants.PasswordFlags, ",") for i, arg := range masked { for _, flag := range passwordFlags { if strings.HasPrefix(arg, flag+"=") { // Формат: --flag=value parts := strings.SplitN(arg, "=", 2) if len(parts) == 2 { masked[i] = parts[0] + "=" + constants.PasswordMask } } else if arg == flag && i+1 < len(masked) { // Формат: --flag value masked[i+1] = constants.PasswordMask } } } return masked }