Files
bwilliams 043e307663 Logging: structured slog messages throughout, and WithLogger options so callers choose the logger
Log messages are lower-case event names with their details as key/value
attributes ("error" for errors), in place of formatted strings.

Loggable package take a WithLogger option as part of their "New*" call,
defaulting to slog.Default(). Each tags its lines with its `component`.

Some debug loggers print directly rather than using slog when in
terminal logging mode.
2026-10-15 16:10:52 +01:00

91 lines
2.2 KiB
Go

package config
import (
"context"
"fmt"
"log/slog"
"os"
"reflect"
"slices"
"strings"
"github.com/spf13/viper"
"git.avsdev.uk/Go/job-search/internal/logging"
)
// printEnv logs each JOBSEARCH* environment variable at debug level. On a
// terminal it logs one line and prints the variables under it as
// "name=value" lines; elsewhere each variable is a log entry of its own.
func printEnv() {
logger := slog.Default()
terminal := logging.WritesToTerminal(logger.Handler())
if terminal && !logger.Enabled(context.Background(), slog.LevelDebug) {
return
}
var variables []string
for _, variable := range os.Environ() {
if strings.HasPrefix(variable, EnvPrefix) {
variables = append(variables, variable)
}
}
slices.Sort(variables)
if terminal {
logger.Debug("environment variables", "count", len(variables))
}
for _, variable := range variables {
if terminal {
logging.PrintToTerminal("\t" + variable)
continue
}
name, value, _ := strings.Cut(variable, "=")
logger.Debug("environment variable", "name", name, "value", value)
}
}
// printLoadedConfig logs every key set by the config file or an environment
// variable (see isExplicitlySet), with its value and type, at debug level. On
// a terminal it logs one line and prints the values under it as
// "key = value <type>" lines; elsewhere each value is a log entry of its own.
func printLoadedConfig() {
logger := slog.Default()
terminal := logging.WritesToTerminal(logger.Handler())
if terminal && !logger.Enabled(context.Background(), slog.LevelDebug) {
return
}
var keys []string
for _, key := range viper.AllKeys() {
if isExplicitlySet(key) {
keys = append(keys, key)
}
}
if terminal {
logger.Debug("loaded config values", "count", len(keys))
}
for _, key := range keys {
value := viper.Get(key)
kind := reflect.TypeOf(value).Kind().String()
if terminal {
logging.PrintToTerminal(
fmt.Sprintf("\t%s = %#v <%s>", key, value, kind),
)
continue
}
logger.Debug(
"loaded config value",
"key", key,
"value", value,
"type", kind,
)
}
}
// printConfig logs conf at debug level.
func printConfig(conf JobSearchConfig) {
conf.PrintLog(slog.LevelDebug)
}