package config import ( "encoding/json" "fmt" "log" "os" "time" "go.uber.org/zap" "go.uber.org/zap/zapcore" "go.c3c.cz/cv/app/server/internal/version" ) type FrontendConfigDef struct { CommitTime string `json:"commitTime"` } var ( BindAddrPprof = confString("BIND_ADDR_PPROF", "localhost:6060", false) BindAddrHttp = confString("BIND_ADDR_HTTP", ":8080", false) GraceTerminationDelay = confDuration("GRACE_TERMINATION_DELAY", 0) GraceTerminationLimit = confDuration("GRACE_TERMINATION_LIMIT", 10*time.Second) LoggerConfig *zap.Config loggingLevel = confString("LOGGING_LEVEL", "info", false) Frontend string ) func init() { b, err := json.Marshal(FrontendConfigDef{ CommitTime: version.CommitTime.Format(time.RFC3339), }) if err != nil { log.Fatal(err) } Frontend = string(b) zapConfig := confString("LOGGER_CONFIG", "", false) var l zapcore.Level if err := l.UnmarshalText([]byte(loggingLevel)); err != nil { log.Fatal(fmt.Errorf("could not create debug level from env: %w", err)) } if zapConfig != "" { if err := json.Unmarshal([]byte(zapConfig), &LoggerConfig); err != nil { log.Fatal(fmt.Errorf("could not create logging configuration from env: %w", err)) } // Warn if both logger config and logging level are specified _, loggingLevelPresent := os.LookupEnv("LOGGING_LEVEL") if loggingLevelPresent { log.Println("cannot have both LOGGING_CONFIG and LOGGING_LEVEL environment configuration values") LoggerConfig.Level = zap.NewAtomicLevelAt(l) } } else { loggerConfig := zap.NewProductionConfig() encoderConfig := zap.NewProductionEncoderConfig() encoderConfig.TimeKey = "t" encoderConfig.LevelKey = "l" encoderConfig.CallerKey = "c" encoderConfig.MessageKey = "m" encoderConfig.StacktraceKey = "s" encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder encoderConfig.EncodeTime = zapcore.RFC3339NanoTimeEncoder encoderConfig.EncodeDuration = zapcore.MillisDurationEncoder encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder loggerConfig.EncoderConfig = encoderConfig loggerConfig.Level = zap.NewAtomicLevelAt(l) loggerConfig.Encoding = "json" LoggerConfig = &loggerConfig } } const requiredErrorF = `required variable "%s" not set` func confString(name string, defaultValue string, required bool) string { val, present := os.LookupEnv(name) if !present { if required { log.Fatalf(requiredErrorF, name) } val = defaultValue } return val } func confDuration(name string, defaultValue time.Duration) (val time.Duration) { sVal, present := os.LookupEnv(name) if !present { val = defaultValue } else { var err error val, err = time.ParseDuration(sVal) if err != nil { log.Fatalf(`cannot parse duration variable "%s"`, name) } } return }