From 0763cfee5fc31e6530f6eaec18a291e26765aed0 Mon Sep 17 00:00:00 2001 From: Tulip Blossom Date: Sat, 14 Dec 2024 21:04:31 -0300 Subject: [PATCH] feat: add logging support for all modules + ton of logs --- cmd/root.go | 4 ++- cmd/update.go | 40 ++++++++++++++++---------- drv/brew.go | 21 ++++++++++---- drv/distrobox.go | 22 ++++++++++---- drv/flatpak.go | 21 ++++++++++---- drv/generic.go | 13 +++++++-- drv/rpm-ostree.go | 52 ++++++++++++++++++++-------------- drv/system.go | 51 ++++++++++++++++++++------------- pkg/logging/muteLogger.go | 15 ++++++++-- pkg/logging/userHandler.go | 7 +---- pkg/percent/progressmanager.go | 2 +- pkg/session/session.go | 34 +++++++++++++++++++--- 12 files changed, 192 insertions(+), 90 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 6eddcea..f8e476d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -66,6 +66,7 @@ var ( fLogFile string fLogLevel string fNoLogging bool + fLogJson bool ) func Execute() { @@ -93,7 +94,7 @@ func initLogging(cmd *cobra.Command, args []string) error { return err } - main_app_logger := slog.New(appLogging.SetupAppLogger(logWriter, logLevel, fLogFile != "-")) + main_app_logger := slog.New(appLogging.SetupAppLogger(logWriter, logLevel, fLogFile != "-" || fLogJson)) if fNoLogging { slog.SetDefault(appLogging.NewMuteLogger()) @@ -113,6 +114,7 @@ func init() { rootCmd.Flags().BoolP("verbose", "v", false, "Display command outputs after run") rootCmd.Flags().Bool("ci", false, "Makes some modifications to behavior if is running in CI") + rootCmd.PersistentFlags().BoolVar(&fLogJson, "json", false, "Print logs as json (used for testing)") rootCmd.PersistentFlags().StringVar(&fLogFile, "log-file", "-", "File where user-facing logs will be written to") rootCmd.PersistentFlags().StringVar(&fLogLevel, "log-level", "info", "Log level for user-facing logs") rootCmd.PersistentFlags().BoolVar(&fNoLogging, "quiet", false, "Make logs quiet") diff --git a/cmd/update.go b/cmd/update.go index 724a226..84c13f3 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -76,7 +76,6 @@ func Update(cmd *cobra.Command, args []string) { distroboxUpdater.SetUsers(users) var enableUpd bool = true - var systemOutdated bool rpmOstreeUpdater, err := drv.RpmOstreeUpdater{}.New(*initConfiguration) if err != nil { @@ -97,12 +96,13 @@ func Update(cmd *cobra.Command, args []string) { slog.Debug("Using rpm-ostree fallback as system driver") } - systemUpdater.Config.Enabled = enableUpd && isBootc - rpmOstreeUpdater.Config.Enabled = enableUpd && !isBootc + systemUpdater.Config.Enabled = isBootc && enableUpd + rpmOstreeUpdater.Config.Enabled = !isBootc && enableUpd - var mainSystemDriver drv.SystemUpdateDriver = systemUpdater - if !systemUpdater.Config.Enabled { - mainSystemDriver = rpmOstreeUpdater + // The system driver to be applied needs to have the correct "enabled" value since it will NOT update from here onwards. + var mainSystemDriver drv.SystemUpdateDriver = &systemUpdater + if !isBootc { + mainSystemDriver = &rpmOstreeUpdater } enableUpd, err = mainSystemDriver.Check() @@ -110,9 +110,7 @@ func Update(cmd *cobra.Command, args []string) { slog.Error("Failed checking for updates") } - if !enableUpd { - slog.Debug("No system update found, disabiling module") - } + slog.Debug("System Updater module status", slog.Bool("enabled", enableUpd)) totalSteps := brewUpdater.Steps() + flatpakUpdater.Steps() + distroboxUpdater.Steps() if enableUpd { @@ -149,7 +147,7 @@ func Update(cmd *cobra.Command, args []string) { var outputs = []drv.CommandOutput{} - systemOutdated, err = mainSystemDriver.Outdated() + systemOutdated, err := mainSystemDriver.Outdated() if err != nil { slog.Error("Failed checking if system is out of date") @@ -164,7 +162,11 @@ func Update(cmd *cobra.Command, args []string) { slog.Warn(OUTDATED_WARNING) } + // This section is ugly but we cant really do much about it. + // Using interfaces doesn't preserve the "Config" struct state and I dont know any other way to make this work without cursed workarounds. + if enableUpd { + slog.Debug(fmt.Sprintf("%s module", systemUpdater.Config.Title), slog.String("module_name", systemUpdater.Config.Title), slog.Any("module_configuration", systemUpdater.Config)) percent.ChangeTrackerMessageFancy(pw, tracker, progressEnabled, percent.TrackerMessage{Title: systemUpdater.Config.Title, Description: systemUpdater.Config.Description}) var out *[]drv.CommandOutput out, err = mainSystemDriver.Update() @@ -173,20 +175,28 @@ func Update(cmd *cobra.Command, args []string) { } if brewUpdater.Config.Enabled { + slog.Debug(fmt.Sprintf("%s module", brewUpdater.Config.Title), slog.String("module_name", brewUpdater.Config.Title), slog.Any("module_configuration", brewUpdater.Config)) percent.ChangeTrackerMessageFancy(pw, tracker, progressEnabled, percent.TrackerMessage{Title: brewUpdater.Config.Title, Description: brewUpdater.Config.Description}) - out, err := brewUpdater.Update() + var out *[]drv.CommandOutput + out, err = brewUpdater.Update() outputs = append(outputs, *out...) tracker.IncrementSection(err) } if flatpakUpdater.Config.Enabled { - out, err := flatpakUpdater.Update() + slog.Debug(fmt.Sprintf("%s module", flatpakUpdater.Config.Title), slog.String("module_name", flatpakUpdater.Config.Title), slog.Any("module_configuration", flatpakUpdater.Config)) + percent.ChangeTrackerMessageFancy(pw, tracker, progressEnabled, percent.TrackerMessage{Title: flatpakUpdater.Config.Title, Description: flatpakUpdater.Config.Description}) + var out *[]drv.CommandOutput + out, err = flatpakUpdater.Update() outputs = append(outputs, *out...) tracker.IncrementSection(err) } if distroboxUpdater.Config.Enabled { - out, err := distroboxUpdater.Update() + slog.Debug(fmt.Sprintf("%s module", distroboxUpdater.Config.Title), slog.String("module_name", distroboxUpdater.Config.Title), slog.Any("module_configuration", distroboxUpdater.Config)) + percent.ChangeTrackerMessageFancy(pw, tracker, progressEnabled, percent.TrackerMessage{Title: distroboxUpdater.Config.Title, Description: distroboxUpdater.Config.Description}) + var out *[]drv.CommandOutput + out, err = distroboxUpdater.Update() outputs = append(outputs, *out...) tracker.IncrementSection(err) } @@ -199,7 +209,7 @@ func Update(cmd *cobra.Command, args []string) { slog.Info("Verbose run requested") for _, output := range outputs { - slog.Info(output.Context, slog.String("stdout", output.Stdout), slog.Any("stderr", output.Stderr), slog.Any("cli", output.Cli)) + slog.Info(output.Context, slog.Any("output", output)) } return @@ -216,7 +226,7 @@ func Update(cmd *cobra.Command, args []string) { slog.Warn("Exited with failed updates.") for _, output := range failures { - slog.Info(output.Context, slog.String("stdout", output.Stdout), slog.Any("stderr", output.Stderr), slog.Any("cli", output.Cli)) + slog.Info(output.Context, slog.Any("output", output)) } return diff --git a/drv/brew.go b/drv/brew.go index 70ea79b..f934d91 100644 --- a/drv/brew.go +++ b/drv/brew.go @@ -2,7 +2,9 @@ package drv import ( "fmt" + "log/slog" "os" + "strings" "syscall" "github.com/ublue-os/uupd/pkg/session" @@ -31,9 +33,8 @@ func (up BrewUpdater) Steps() int { return 0 } -func (up BrewUpdater) Check() (*[]CommandOutput, error) { - // TODO: implement - return nil, nil +func (up BrewUpdater) Check() (bool, error) { + return true, nil } func (up BrewUpdater) Update() (*[]CommandOutput, error) { @@ -44,7 +45,7 @@ func (up BrewUpdater) Update() (*[]CommandOutput, error) { } cli := []string{up.BrewPath, "update"} - out, err := session.RunUID(up.BaseUser, cli, up.Config.Environment) + out, err := session.RunUID(up.Config.logger, slog.LevelDebug, up.BaseUser, cli, up.Config.Environment) tmpout := CommandOutput{}.New(out, err) tmpout.Context = "Brew Update" tmpout.Cli = cli @@ -56,7 +57,7 @@ func (up BrewUpdater) Update() (*[]CommandOutput, error) { } cli = []string{up.BrewPath, "upgrade"} - out, err = session.RunUID(up.BaseUser, cli, up.Config.Environment) + out, err = session.RunUID(up.Config.logger, slog.LevelDebug, up.BaseUser, cli, up.Config.Environment) tmpout = CommandOutput{}.New(out, err) tmpout.Context = "Brew Upgrade" tmpout.Cli = cli @@ -75,7 +76,6 @@ type BrewUpdater struct { } func (up BrewUpdater) New(config UpdaterInitConfiguration) (BrewUpdater, error) { - up.Config = DriverConfiguration{ Title: "Brew", Description: "CLI Apps", @@ -84,6 +84,7 @@ func (up BrewUpdater) New(config UpdaterInitConfiguration) (BrewUpdater, error) DryRun: config.DryRun, Environment: config.Environment, } + up.Config.logger = config.Logger.With(slog.String("module", strings.ToLower(up.Config.Title))) brewPrefix, exists := up.Config.Environment["HOMEBREW_PREFIX"] if !exists || brewPrefix == "" { @@ -122,3 +123,11 @@ func (up BrewUpdater) New(config UpdaterInitConfiguration) (BrewUpdater, error) return up, nil } + +func (up *BrewUpdater) Logger() *slog.Logger { + return up.Config.logger +} + +func (up *BrewUpdater) SetLogger(logger *slog.Logger) { + up.Config.logger = logger +} diff --git a/drv/distrobox.go b/drv/distrobox.go index 7754dd7..5db751c 100644 --- a/drv/distrobox.go +++ b/drv/distrobox.go @@ -1,6 +1,9 @@ package drv import ( + "log/slog" + "strings" + "github.com/ublue-os/uupd/pkg/percent" "github.com/ublue-os/uupd/pkg/session" ) @@ -35,6 +38,7 @@ func (up DistroboxUpdater) New(config UpdaterInitConfiguration) (DistroboxUpdate DryRun: config.DryRun, Environment: config.Environment, } + up.Config.logger = config.Logger.With(slog.String("module", strings.ToLower(up.Config.Title))) up.usersEnabled = false up.Tracker = nil @@ -53,11 +57,11 @@ func (up *DistroboxUpdater) SetUsers(users []session.User) { up.usersEnabled = true } -func (up DistroboxUpdater) Check() (*[]CommandOutput, error) { - return nil, nil +func (up DistroboxUpdater) Check() (bool, error) { + return true, nil } -func (up *DistroboxUpdater) Update() (*[]CommandOutput, error) { +func (up DistroboxUpdater) Update() (*[]CommandOutput, error) { var finalOutput = []CommandOutput{} if up.Config.DryRun { @@ -74,7 +78,7 @@ func (up *DistroboxUpdater) Update() (*[]CommandOutput, error) { percent.ChangeTrackerMessageFancy(*up.Tracker.Writer, up.Tracker.Tracker, up.Tracker.Progress, percent.TrackerMessage{Title: up.Config.Title, Description: up.Config.Description}) cli := []string{up.binaryPath, "upgrade", "-a"} - out, err := session.RunUID(0, cli, nil) + out, err := session.RunUID(up.Config.logger, slog.LevelDebug, 0, cli, nil) tmpout := CommandOutput{}.New(out, err) tmpout.Context = up.Config.Description tmpout.Cli = cli @@ -87,7 +91,7 @@ func (up *DistroboxUpdater) Update() (*[]CommandOutput, error) { context := *up.Config.UserDescription + " " + user.Name percent.ChangeTrackerMessageFancy(*up.Tracker.Writer, up.Tracker.Tracker, up.Tracker.Progress, percent.TrackerMessage{Title: up.Config.Title, Description: *up.Config.UserDescription + " " + user.Name}) cli := []string{up.binaryPath, "upgrade", "-a"} - out, err := session.RunUID(user.UID, cli, nil) + out, err := session.RunUID(up.Config.logger, slog.LevelDebug, user.UID, cli, nil) tmpout = CommandOutput{}.New(out, err) tmpout.Context = context tmpout.Cli = cli @@ -96,3 +100,11 @@ func (up *DistroboxUpdater) Update() (*[]CommandOutput, error) { } return &finalOutput, nil } + +func (up *DistroboxUpdater) Logger() *slog.Logger { + return up.Config.logger +} + +func (up *DistroboxUpdater) SetLogger(logger *slog.Logger) { + up.Config.logger = logger +} diff --git a/drv/flatpak.go b/drv/flatpak.go index ee76e13..1c42e1c 100644 --- a/drv/flatpak.go +++ b/drv/flatpak.go @@ -1,7 +1,9 @@ package drv import ( + "log/slog" "os/exec" + "strings" "github.com/ublue-os/uupd/pkg/percent" "github.com/ublue-os/uupd/pkg/session" @@ -37,6 +39,7 @@ func (up FlatpakUpdater) New(config UpdaterInitConfiguration) (FlatpakUpdater, e DryRun: config.DryRun, Environment: config.Environment, } + up.Config.logger = config.Logger.With(slog.String("module", strings.ToLower(up.Config.Title))) up.usersEnabled = false up.Tracker = nil @@ -55,8 +58,8 @@ func (up *FlatpakUpdater) SetUsers(users []session.User) { up.usersEnabled = true } -func (up FlatpakUpdater) Check() (*[]CommandOutput, error) { - return nil, nil +func (up FlatpakUpdater) Check() (bool, error) { + return true, nil } func (up FlatpakUpdater) Update() (*[]CommandOutput, error) { @@ -75,9 +78,9 @@ func (up FlatpakUpdater) Update() (*[]CommandOutput, error) { } percent.ChangeTrackerMessageFancy(*up.Tracker.Writer, up.Tracker.Tracker, up.Tracker.Progress, percent.TrackerMessage{Title: up.Config.Title, Description: up.Config.Description}) - cli := []string{up.binaryPath, "update", "-y"} + cli := []string{up.binaryPath, "update", "-y", "--noninteractive"} flatpakCmd := exec.Command(cli[0], cli[1:]...) - out, err := flatpakCmd.CombinedOutput() + out, err := session.RunLog(up.Config.logger, slog.LevelDebug, flatpakCmd) tmpout := CommandOutput{}.New(out, err) tmpout.Context = up.Config.Description tmpout.Cli = cli @@ -90,7 +93,7 @@ func (up FlatpakUpdater) Update() (*[]CommandOutput, error) { context := *up.Config.UserDescription + " " + user.Name percent.ChangeTrackerMessageFancy(*up.Tracker.Writer, up.Tracker.Tracker, up.Tracker.Progress, percent.TrackerMessage{Title: up.Config.Title, Description: context}) cli := []string{up.binaryPath, "update", "-y"} - out, err := session.RunUID(user.UID, cli, nil) + out, err := session.RunUID(up.Config.logger, slog.LevelDebug, user.UID, cli, nil) tmpout = CommandOutput{}.New(out, err) tmpout.Context = context tmpout.Cli = cli @@ -99,3 +102,11 @@ func (up FlatpakUpdater) Update() (*[]CommandOutput, error) { } return &finalOutput, nil } + +func (up *FlatpakUpdater) Logger() *slog.Logger { + return up.Config.logger +} + +func (up *FlatpakUpdater) SetLogger(logger *slog.Logger) { + up.Config.logger = logger +} diff --git a/drv/generic.go b/drv/generic.go index 95a7d1c..ae0e4c7 100644 --- a/drv/generic.go +++ b/drv/generic.go @@ -1,6 +1,7 @@ package drv import ( + "log/slog" "os" "strings" @@ -16,6 +17,7 @@ type UpdaterInitConfiguration struct { Ci bool Verbose bool Environment EnvironmentMap + Logger *slog.Logger } func GetEnvironment(data []string, getkeyval func(item string) (key, val string)) map[string]string { @@ -36,6 +38,7 @@ func (up UpdaterInitConfiguration) New() *UpdaterInitConfiguration { val = splits[1] return }) + up.Logger = slog.Default() return &up } @@ -68,7 +71,8 @@ type DriverConfiguration struct { Enabled bool MultiUser bool DryRun bool - Environment EnvironmentMap + Environment EnvironmentMap `json:"-"` + logger *slog.Logger `json:"-"` UserDescription *string } @@ -80,9 +84,12 @@ type TrackerConfiguration struct { type UpdateDriver interface { Steps() int - Check() (*[]CommandOutput, error) + Check() (bool, error) Update() (*[]CommandOutput, error) - New(config UpdaterInitConfiguration) (*UpdateDriver, error) + Config() *DriverConfiguration + SetEnabled(value bool) + Logger() *slog.Logger + SetLogger(value *slog.Logger) } type MultiUserUpdateDriver interface { diff --git a/drv/rpm-ostree.go b/drv/rpm-ostree.go index dca9bf4..23cb540 100644 --- a/drv/rpm-ostree.go +++ b/drv/rpm-ostree.go @@ -5,6 +5,8 @@ package drv import ( "encoding/json" + "github.com/ublue-os/uupd/pkg/session" + "log/slog" "os/exec" "strings" "time" @@ -21,15 +23,15 @@ type RpmOstreeUpdater struct { BinaryPath string } -func (dr RpmOstreeUpdater) Outdated() (bool, error) { - if dr.Config.DryRun { +func (up RpmOstreeUpdater) Outdated() (bool, error) { + if up.Config.DryRun { return false, nil } oneMonthAgo := time.Now().AddDate(0, -1, 0) var timestamp time.Time - cmd := exec.Command(dr.BinaryPath, "status", "--json", "--booted") - out, err := cmd.CombinedOutput() + cmd := exec.Command(up.BinaryPath, "status", "--json", "--booted") + out, err := session.RunLog(up.Config.logger, slog.LevelDebug, cmd) if err != nil { return false, err } @@ -43,32 +45,20 @@ func (dr RpmOstreeUpdater) Outdated() (bool, error) { return timestamp.Before(oneMonthAgo), nil } -func (dr RpmOstreeUpdater) Update() (*[]CommandOutput, error) { +func (up RpmOstreeUpdater) Update() (*[]CommandOutput, error) { var finalOutput = []CommandOutput{} var cmd *exec.Cmd - binaryPath := dr.BinaryPath + binaryPath := up.BinaryPath cli := []string{binaryPath, "upgrade"} - cmd = exec.Command(cli[0], cli[1:]...) - out, err := cmd.CombinedOutput() + out, err := session.RunLog(up.Config.logger, slog.LevelDebug, cmd) tmpout := CommandOutput{}.New(out, err) - // tmpout.Cli = cli + tmpout.Cli = cli tmpout.Failure = err != nil tmpout.Context = "System Update" finalOutput = append(finalOutput, *tmpout) return &finalOutput, err } -func (dr RpmOstreeUpdater) UpdateAvailable() (bool, error) { - // This function may or may not be accurate, rpm-ostree updgrade --check has issues... https://github.com/coreos/rpm-ostree/issues/1579 - // Not worried because we will end up removing rpm-ostree from the equation soon - cmd := exec.Command(dr.BinaryPath, "upgrade", "--check") - out, err := cmd.CombinedOutput() - if err != nil { - return true, err - } - return strings.Contains(string(out), "AvailableUpdate"), nil -} - func (up RpmOstreeUpdater) Steps() int { if up.Config.Enabled { return 1 @@ -98,7 +88,7 @@ func (up RpmOstreeUpdater) New(config UpdaterInitConfiguration) (RpmOstreeUpdate DryRun: config.DryRun, Environment: config.Environment, } - + up.Config.logger = config.Logger.With(slog.String("module", strings.ToLower(up.Config.Title))) if up.Config.DryRun { return up, nil } @@ -118,5 +108,23 @@ func (up RpmOstreeUpdater) Check() (bool, error) { return true, nil } - return up.UpdateAvailable() + // This function may or may not be accurate, rpm-ostree updgrade --check has issues... https://github.com/coreos/rpm-ostree/issues/1579 + // Not worried because we will end up removing rpm-ostree from the equation soon + cmd := exec.Command(up.BinaryPath, "upgrade", "--check") + out, err := cmd.CombinedOutput() + if err != nil { + return true, err + } + + updateNecessary := strings.Contains(string(out), "AvailableUpdate") + up.Config.logger.Debug("Executed update check", slog.String("output", string(out)), slog.Bool("update", updateNecessary)) + return updateNecessary, nil +} + +func (up *RpmOstreeUpdater) Logger() *slog.Logger { + return up.Config.logger +} + +func (up *RpmOstreeUpdater) SetLogger(logger *slog.Logger) { + up.Config.logger = logger } diff --git a/drv/system.go b/drv/system.go index 1e7c2d1..3cf6cc6 100644 --- a/drv/system.go +++ b/drv/system.go @@ -2,9 +2,12 @@ package drv import ( "encoding/json" + "log/slog" "os/exec" "strings" "time" + + "github.com/ublue-os/uupd/pkg/session" ) type bootcStatus struct { @@ -29,9 +32,10 @@ type bootcStatus struct { type SystemUpdateDriver interface { Steps() int Outdated() (bool, error) - UpdateAvailable() (bool, error) Check() (bool, error) Update() (*[]CommandOutput, error) + Logger() *slog.Logger + SetLogger(value *slog.Logger) } type SystemUpdater struct { @@ -39,13 +43,13 @@ type SystemUpdater struct { BinaryPath string } -func (dr SystemUpdater) Outdated() (bool, error) { - if dr.Config.DryRun { +func (up SystemUpdater) Outdated() (bool, error) { + if up.Config.DryRun { return false, nil } oneMonthAgo := time.Now().AddDate(0, -1, 0) var timestamp time.Time - cmd := exec.Command(dr.BinaryPath, "status", "--format=json") + cmd := exec.Command(up.BinaryPath, "status", "--format=json") out, err := cmd.CombinedOutput() if err != nil { return false, err @@ -62,13 +66,14 @@ func (dr SystemUpdater) Outdated() (bool, error) { return timestamp.Before(oneMonthAgo), nil } -func (dr SystemUpdater) Update() (*[]CommandOutput, error) { +func (up SystemUpdater) Update() (*[]CommandOutput, error) { var finalOutput = []CommandOutput{} var cmd *exec.Cmd - binaryPath := dr.BinaryPath - cli := []string{binaryPath, "upgrade"} + binaryPath := up.BinaryPath + cli := []string{binaryPath, "upgrade", "--quiet"} + up.Config.logger.Debug("Executing update", slog.Any("cli", cli)) cmd = exec.Command(cli[0], cli[1:]...) - out, err := cmd.CombinedOutput() + out, err := session.RunLog(up.Config.logger, slog.LevelDebug, cmd) tmpout := CommandOutput{}.New(out, err) if err != nil { tmpout.SetFailureContext("System update") @@ -77,15 +82,6 @@ func (dr SystemUpdater) Update() (*[]CommandOutput, error) { return &finalOutput, err } -func (dr SystemUpdater) UpdateAvailable() (bool, error) { - cmd := exec.Command(dr.BinaryPath, "upgrade", "--check") - out, err := cmd.CombinedOutput() - if err != nil { - return true, err - } - return !strings.Contains(string(out), "No changes in:"), nil -} - func (up SystemUpdater) Steps() int { if up.Config.Enabled { return 1 @@ -95,13 +91,13 @@ func (up SystemUpdater) Steps() int { func (up SystemUpdater) New(config UpdaterInitConfiguration) (SystemUpdater, error) { up.Config = DriverConfiguration{ - Title: "Bootc", + Title: "System", Description: "System Image", Enabled: !config.Ci, DryRun: config.DryRun, Environment: config.Environment, } - + up.Config.logger = config.Logger.With(slog.String("module", strings.ToLower(up.Config.Title))) if up.Config.DryRun { return up, nil } @@ -121,5 +117,20 @@ func (up SystemUpdater) Check() (bool, error) { return true, nil } - return up.UpdateAvailable() + cmd := exec.Command(up.BinaryPath, "upgrade", "--check") + out, err := cmd.CombinedOutput() + if err != nil { + return true, err + } + updateNecessary := !strings.Contains(string(out), "No changes in:") + up.Config.logger.Debug("Executed update check", slog.String("output", string(out)), slog.Bool("update", updateNecessary)) + return updateNecessary, nil +} + +func (up *SystemUpdater) Logger() *slog.Logger { + return up.Config.logger +} + +func (up *SystemUpdater) SetLogger(logger *slog.Logger) { + up.Config.logger = logger } diff --git a/pkg/logging/muteLogger.go b/pkg/logging/muteLogger.go index 1957474..78d7ed5 100644 --- a/pkg/logging/muteLogger.go +++ b/pkg/logging/muteLogger.go @@ -1,10 +1,21 @@ package logging import ( - "io" + "context" "log/slog" ) func NewMuteLogger() *slog.Logger { - return slog.New(slog.NewTextHandler(io.Discard, nil)) + return slog.New(DiscardHandler) } + +// DiscardHandler discards all log output. +// DiscardHandler.Enabled returns false for all Levels. +var DiscardHandler slog.Handler = discardHandler{} + +type discardHandler struct{} + +func (dh discardHandler) Enabled(context.Context, slog.Level) bool { return false } +func (dh discardHandler) Handle(context.Context, slog.Record) error { return nil } +func (dh discardHandler) WithAttrs(attrs []slog.Attr) slog.Handler { return dh } +func (dh discardHandler) WithGroup(name string) slog.Handler { return dh } diff --git a/pkg/logging/userHandler.go b/pkg/logging/userHandler.go index 4372310..1452a6b 100644 --- a/pkg/logging/userHandler.go +++ b/pkg/logging/userHandler.go @@ -96,12 +96,7 @@ func (h *UserHandler) Handle(ctx context.Context, r slog.Record) error { colorize(lightGray, r.Time.Format(timeFormat)), level, colorize(white, r.Message), - func() string { - if len(trimmedBytes) > 0 && trimmedBytes != "{}" { - return colorize(darkGray, "\n"+trimmedBytes) - } - return "" - }(), + colorize(darkGray, "\n"+trimmedBytes), ) return nil diff --git a/pkg/percent/progressmanager.go b/pkg/percent/progressmanager.go index 10e5dbd..d85aee2 100644 --- a/pkg/percent/progressmanager.go +++ b/pkg/percent/progressmanager.go @@ -70,7 +70,7 @@ func NewProgressWriter() progress.Writer { var accentColorSet progress.StyleColors // Get accent color: https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Settings.html cli := []string{"busctl", "--user", "--json=short", "call", "org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop", "org.freedesktop.portal.Settings", "ReadOne", "ss", "org.freedesktop.appearance", "accent-color"} - out, err := session.RunUID(targetUser, cli, nil) + out, err := session.RunUID(nil, slog.LevelDebug, targetUser, cli, nil) if err != nil { return pw } diff --git a/pkg/session/session.go b/pkg/session/session.go index 23a5a1d..bbc5c1f 100644 --- a/pkg/session/session.go +++ b/pkg/session/session.go @@ -1,9 +1,13 @@ package session import ( + "bufio" "fmt" - "github.com/godbus/dbus/v5" + "io" + "log/slog" "os/exec" + + "github.com/godbus/dbus/v5" ) type User struct { @@ -11,7 +15,29 @@ type User struct { Name string } -func RunUID(uid int, command []string, env map[string]string) ([]byte, error) { +// Runs any specified Command while logging it to the logger +// Made to work just like (Command).CombinedOutput() +func RunLog(logger *slog.Logger, level slog.Level, command *exec.Cmd) ([]byte, error) { + if logger == nil { + return command.CombinedOutput() + } + + stdout, _ := command.StdoutPipe() + stderr, _ := command.StderrPipe() + multiReader := io.MultiReader(stdout, stderr) + + command.Start() + scanner := bufio.NewScanner(multiReader) + scanner.Split(bufio.ScanLines) + for scanner.Scan() { + logger.With(slog.Bool("subcommand", true)).Log(nil, level, scanner.Text()) + } + command.Wait() + + return scanner.Bytes(), scanner.Err() +} + +func RunUID(logger *slog.Logger, level slog.Level, uid int, command []string, env map[string]string) ([]byte, error) { // Just fork systemd-run, we don't need to rewrite systemd-run with dbus cmdArgs := []string{ "/usr/bin/systemd-run", @@ -27,7 +53,7 @@ func RunUID(uid int, command []string, env map[string]string) ([]byte, error) { cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) - return cmd.CombinedOutput() + return RunLog(logger, level, cmd) } func ListUsers() ([]User, error) { @@ -77,7 +103,7 @@ func Notify(summary string, body string) error { } for _, user := range users { // we don't care if these exit - _, _ = RunUID(user.UID, []string{"/usr/bin/notify-send", "--app-name", "uupd", summary, body}, nil) + _, _ = RunUID(slog.Default(), slog.LevelDebug, user.UID, []string{"/usr/bin/notify-send", "--app-name", "uupd", summary, body}, nil) } return nil }