|
|
|
|
@@ -118,6 +118,34 @@ type SamplerConfig struct {
|
|
|
|
|
Ratio float64 `mapstructure:"ratio"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// peekJSONLogging determines whether JSON logging should be used before the full
|
|
|
|
|
// config is loaded, solving the chicken-and-egg problem where the logger format
|
|
|
|
|
// must be known before any log is emitted, yet the format is stored in the config.
|
|
|
|
|
//
|
|
|
|
|
// Resolution order (mirrors Viper's own priority):
|
|
|
|
|
// 1. DLC_LOGGING_JSON env var — checked directly via os.Getenv (zero overhead)
|
|
|
|
|
// 2. logging.json key in the config file — read with a minimal throwaway Viper
|
|
|
|
|
// instance so we don't parse the whole config twice unnecessarily
|
|
|
|
|
func peekJSONLogging() bool {
|
|
|
|
|
// 1. Env var takes highest priority — check it first
|
|
|
|
|
if env := os.Getenv("DLC_LOGGING_JSON"); env != "" {
|
|
|
|
|
return strings.EqualFold(env, "true") || env == "1"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. Try to read logging.json from the config file
|
|
|
|
|
preV := viper.New()
|
|
|
|
|
preV.SetDefault("logging.json", false)
|
|
|
|
|
if configFile := os.Getenv("DLC_CONFIG_FILE"); configFile != "" {
|
|
|
|
|
preV.SetConfigFile(configFile)
|
|
|
|
|
} else {
|
|
|
|
|
preV.SetConfigName("config")
|
|
|
|
|
preV.SetConfigType("yaml")
|
|
|
|
|
preV.AddConfigPath(".")
|
|
|
|
|
}
|
|
|
|
|
_ = preV.ReadInConfig() // ignore errors — defaults apply on failure
|
|
|
|
|
return preV.GetBool("logging.json")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// LoadConfig loads configuration from file, environment variables, and defaults
|
|
|
|
|
// Configuration priority: file > environment variables > defaults
|
|
|
|
|
// To specify a custom config file path, set DLC_CONFIG_FILE environment variable
|
|
|
|
|
@@ -129,9 +157,17 @@ func LoadConfig() (*Config, error) {
|
|
|
|
|
|
|
|
|
|
v := viper.New()
|
|
|
|
|
|
|
|
|
|
// Set up initial console logging for config loading messages
|
|
|
|
|
consoleWriter := zerolog.ConsoleWriter{Out: os.Stderr}
|
|
|
|
|
log.Logger = log.Output(consoleWriter)
|
|
|
|
|
// Configure the logger format before emitting any log output.
|
|
|
|
|
// peekJSONLogging reads the JSON setting early (env var + config file pre-read)
|
|
|
|
|
// so that every log line — including those produced during config loading — is
|
|
|
|
|
// already in the correct format.
|
|
|
|
|
jsonLogging := peekJSONLogging()
|
|
|
|
|
if jsonLogging {
|
|
|
|
|
log.Logger = log.Output(os.Stderr)
|
|
|
|
|
} else {
|
|
|
|
|
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
|
|
|
|
}
|
|
|
|
|
log.Info().Bool("json", jsonLogging).Msg("Logging configured")
|
|
|
|
|
|
|
|
|
|
// Set default values
|
|
|
|
|
v.SetDefault("server.host", "0.0.0.0")
|
|
|
|
|
@@ -227,15 +263,9 @@ func LoadConfig() (*Config, error) {
|
|
|
|
|
return nil, fmt.Errorf("config unmarshal error: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Configure log output format (JSON or console) first
|
|
|
|
|
if config.Logging.JSON {
|
|
|
|
|
log.Logger = log.Output(os.Stderr)
|
|
|
|
|
} else {
|
|
|
|
|
consoleWriter := zerolog.ConsoleWriter{Out: os.Stderr}
|
|
|
|
|
log.Logger = log.Output(consoleWriter)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Setup logging based on configuration
|
|
|
|
|
// Setup logging based on configuration (level, output file, time format).
|
|
|
|
|
// The JSON/console format was already applied at the top of LoadConfig via
|
|
|
|
|
// peekJSONLogging, so SetupLogging only needs to handle the remaining knobs.
|
|
|
|
|
config.SetupLogging()
|
|
|
|
|
|
|
|
|
|
log.Info().
|
|
|
|
|
|