diff --git a/cmd/doltsrht/logging.go b/cmd/doltsrht/logging.go index cb03a0c53d21fc9a95ea27180ee6f1589fc0b757..d0e5d13c0f2ae727b209955d47ead074d23669ed 100644 --- a/cmd/doltsrht/logging.go +++ b/cmd/doltsrht/logging.go @@ -1,15 +1,13 @@ package main import ( - "log/slog" "os" - "time" "github.com/vaughan0/go-ini" "go.bigb.es/auxilia/scribe" - "sourcecraft.dev/bigbes/sr-ht-core/config" + "sourcecraft.dev/bigbes/sr-ht-ecore/logging" ) // setupLogging installs the process-wide slog handler. @@ -23,38 +21,39 @@ // skipped this call would still log all of it — into Go's plain stderr handler, // without a level, without source positions, and above all without the masking // below. // -// The level comes from [dolt.sr.ht]log-level ("debug", "info", "warn", -// "error"); an unreadable value is info, because a daemon that refused to boot -// over a typo in a log level would be trading an operator's whole service for -// their logging preference. +// The policy is sr-ht-ecore's and the handler is ours, which is the split that +// package documents: the level, the colour decision and — the part that is not +// presentation — the set of attribute keys that must never reach a log file are +// facts about this instance and are maintained once, while the handler that +// spends them stays here, because a service wanting a JSON handler for a log +// shipper should not have to link a tinting one to share a mask list. +// +// The verbosity is [dolt.sr.ht]log-level ("debug", "info", "warn", "error") as +// before, and now also $LOG_LEVEL and the -d every SourceHut daemon takes. -d is +// resolved here rather than left to server.New because server.New runs after +// config loading and validation: a daemon that becomes verbose only once it has +// started is silent for exactly the window an operator passes -d to watch. An +// unreadable value is info, because a daemon that refused to boot over a typo in +// a log level would be trading an operator's whole service for their logging +// preference. func setupLogging(conf ini.File) { - var level slog.Level - if err := level.UnmarshalText([]byte(config.GetString(conf, serviceName, "log-level", "info"))); err != nil { - level = slog.LevelInfo - } + opts := logging.Defaults(conf, serviceName) - slog.SetDefault(slog.New(scribe.NewTintHandler( + logging.Install(scribe.NewTintHandler( scribe.WithWriter(os.Stderr), - scribe.WithLevel(level), - scribe.WithSource(true), - scribe.WithTimeFormat(time.DateTime), + scribe.WithLevel(opts.Level), + scribe.WithSource(opts.AddSource), + scribe.WithTimeFormat(opts.TimeFormat), // Colour is for a terminal; under systemd or a container's log // collector the escapes are noise in the journal. - scribe.WithNoColor(!isTerminal(os.Stderr)), + scribe.WithNoColor(!opts.Color), // The masks are keyed on the attribute *path*, not on the message, so // they cost nothing in prose and cannot be defeated by a sentence that - // happens to contain the word "token". These three are the credentials - // this service handles: the unified-login cookie, the "Internal" - // service-to-service fernet token and the Authorization header the - // remotesapi interceptors read a PAT or a keypair JWT out of. - scribe.WithMaskKeys("token", "cookie", "authorization"), - scribe.WithMask(`(?i)(secret|token|api_?key|password|pubkey|credential)`, "***"), - ))) -} - -// isTerminal reports whether f is a character device, which is the whole of -// what the colour decision needs and does not require a dependency to answer. -func isTerminal(f *os.File) bool { - info, err := f.Stat() - return err == nil && info.Mode()&os.ModeCharDevice != 0 + // happens to contain the word "token". Taking the instance's list rather + // than this service's three adds the keys the siblings had learned to + // redact and this one had not — the network and webhook private keys out + // of config.ini, and the migration DSN, which carries a password. + scribe.WithMaskKeys(opts.MaskKeys...), + scribe.WithMask(opts.MaskPattern, opts.MaskReplacement), + )) } diff --git a/config.example.ini b/config.example.ini index 756bb0fcfc91d0a76e0961cb8930c02eca63831e..048833a87d2fd6d38149cf3cb92462e78b8835f1 100644 --- a/config.example.ini +++ b/config.example.ini @@ -42,6 +42,10 @@ ; ; Verbosity of the daemon's structured log: debug, info, warn or error. An ; unreadable value is read as info rather than refusing to boot — a typo in a ; logging preference must not cost the service. +; +; This is the persistent setting. For one run, $LOG_LEVEL overrides it and the +; -d flag overrides both — and both apply from the first line of startup, before +; the config below has been read. log-level=info ; ---------------------------------------------------------------------------