package config import ( "fmt" "os" "strconv" "strings" "time" ) const defaultEnvPrefix = "GO_OMNI_" // LoadFromEnv loads application settings from GO_OMNI_* variables. The // database settings remain owned by database.ConfigFromEnv. func LoadFromEnv(prefix string) (Config, error) { prefix = strings.TrimSpace(prefix) if prefix == "" { prefix = defaultEnvPrefix } cfg := Default() cfg.Address = envString(prefix+"HTTP_ADDR", cfg.Address) cfg.RequestIDHeader = envString(prefix+"REQUEST_ID_HEADER", cfg.RequestIDHeader) cfg.Log.Level = envString(prefix+"LOG_LEVEL", cfg.Log.Level) cfg.Log.Format = envString(prefix+"LOG_FORMAT", cfg.Log.Format) cfg.Log.Output = envString(prefix+"LOG_OUTPUT", cfg.Log.Output) cfg.Log.File = envString(prefix+"LOG_FILE", cfg.Log.File) cfg.Log.Service = envString(prefix+"SERVICE", cfg.Log.Service) cfg.Log.Environment = envString(prefix+"ENVIRONMENT", cfg.Log.Environment) var err error if cfg.EnableLogger, err = envBool(prefix+"ENABLE_LOGGER", cfg.EnableLogger); err != nil { return Config{}, err } if cfg.Log.AddSource, err = envBool(prefix+"LOG_ADD_SOURCE", cfg.Log.AddSource); err != nil { return Config{}, err } if value := strings.TrimSpace(os.Getenv(prefix + "SHUTDOWN_TIMEOUT")); value != "" { cfg.ShutdownTimeout, err = time.ParseDuration(value) if err != nil { return Config{}, fmt.Errorf("%sSHUTDOWN_TIMEOUT must be a duration: %w", prefix, err) } } if err := cfg.Validate(); err != nil { return Config{}, err } return cfg, nil } func envString(key, fallback string) string { if value := strings.TrimSpace(os.Getenv(key)); value != "" { return value } return fallback } func envBool(key string, fallback bool) (bool, error) { value := strings.TrimSpace(os.Getenv(key)) if value == "" { return fallback, nil } parsed, err := strconv.ParseBool(value) if err != nil { return false, fmt.Errorf("%s must be a boolean: %w", key, err) } return parsed, nil }