package main
import (
"os"
"github.com/vaughan0/go-ini"
"go.bigb.es/auxilia/scribe"
"sourcecraft.dev/bigbes/sr-ht-ecore/logging"
)
// setupLogging installs the process-wide slog handler.
//
// It sets the *default* logger rather than building one to thread through
// constructors, and that is the point rather than a shortcut. sr-ht-ecore's
// middleware reports a recovered panic through slog's default; so does every
// library package in this service that has no constructor to be handed a logger
// through (authn's cookie and JWT resolvers, the web renderer). A daemon that
// 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 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) {
opts := logging.Defaults(conf, serviceName)
logging.Install(scribe.NewTintHandler(
scribe.WithWriter(os.Stderr),
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(!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". 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),
))
}