From a5448e62a522845797fd7ed3ebcc93a64497f3e7 Mon Sep 17 00:00:00 2001 From: rszyma Date: Thu, 7 Nov 2024 00:56:37 +0100 Subject: [PATCH] feat: add "Show logs" button Previously, with Windows binaries it wasn't possible to see kanata-tray logs, unless recompiled without -H=windowsgui ldflag. Now, we also output logs to a file, so it's not a problem anymore. closes #20 --- .gitignore | 1 + app/app.go | 16 +++++++++++----- config/config.go | 2 +- main.go | 45 +++++++++++++++++++++++++++++++++++---------- 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 25afdbe..7009c59 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ icons .direnv kanata-tray .envrc +kanata_tray_lastrun.log diff --git a/app/app.go b/app/app.go index 2eeb7bf..57a36e4 100644 --- a/app/app.go +++ b/app/app.go @@ -15,6 +15,8 @@ import ( ) type SystrayApp struct { + logFilepath string + concurrentPresets bool // Used when `concurrentPresets` is disabled. @@ -37,16 +39,18 @@ type SystrayApp struct { mPresetLogs []*systray.MenuItem mPresetStatuses []*systray.MenuItem - mOptions *systray.MenuItem - mQuit *systray.MenuItem + mOptions *systray.MenuItem + mShowLogs *systray.MenuItem + mQuit *systray.MenuItem } -func NewSystrayApp(menuTemplate []PresetMenuEntry, layerIcons LayerIcons, allowConcurrentPresets bool) *SystrayApp { +func NewSystrayApp(menuTemplate []PresetMenuEntry, layerIcons LayerIcons, allowConcurrentPresets bool, logFilepath string) *SystrayApp { systray.SetIcon(icons.Default) systray.SetTooltip("kanata-tray") t := &SystrayApp{ + logFilepath: logFilepath, presets: menuTemplate, scheduledPresetIndex: -1, layerIcons: layerIcons, @@ -66,14 +70,14 @@ func NewSystrayApp(menuTemplate []PresetMenuEntry, layerIcons LayerIcons, allowC t.presetCancelFuncs = append(t.presetCancelFuncs, nil) - openLogsItem := menuItem.AddSubMenuItem("Open Logs", "Open Logs") - // openLogsItem.Disable() + openLogsItem := menuItem.AddSubMenuItem("Open kanata logs", "Open kanata log file") t.mPresetLogs = append(t.mPresetLogs, openLogsItem) } systray.AddSeparator() t.mOptions = systray.AddMenuItem("Configure", "Reveals kanata-tray config file") + t.mShowLogs = systray.AddMenuItem("Open logs", "Reveals kanata-tray log file") t.mQuit = systray.AddMenuItem("Exit tray", "Closes kanata (if running) and exits the tray") t.statusClickedCh = multipleMenuItemsClickListener(t.mPresetStatuses) @@ -220,6 +224,8 @@ func (app *SystrayApp) StartProcessingLoop(runner *runner_pkg.Runner, configFold } case <-app.mOptions.ClickedCh: open.Start(configFolder) + case <-app.mShowLogs.ClickedCh: + open.Start(app.logFilepath) case <-app.mQuit.ClickedCh: log.Print("Exiting...") for _, cancel := range app.presetCancelFuncs { diff --git a/config/config.go b/config/config.go index 038757f..e2274fc 100644 --- a/config/config.go +++ b/config/config.go @@ -239,7 +239,7 @@ func ReadConfigOrCreateIfNotExist(configFilePath string) (*Config, error) { cfg2.Presets.Set(layerName, exported) } - pretty.Println("loaded config:", cfg2) + log.Debugf("loaded config: %s", pretty.Sprint(cfg2)) return cfg2, nil } diff --git a/main.go b/main.go index be41619..093d4e9 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "flag" "fmt" + "io" "os" "path/filepath" "runtime" @@ -38,14 +39,6 @@ func main() { os.Exit(1) } - log.SetLevel(log.Lvl(*logLevel)) - log.SetOutput(os.Stderr) - if int(*logLevel) <= int(log.DEBUG) { - log.SetHeader(`${time_rfc3339_nano} ${level} ${short_file}:${line}`) - } else { - log.SetHeader(`${time_rfc3339_nano} ${level}`) - } - err := mainImpl() if err != nil { log.Errorf("kanata-tray exited with an error: %v", err) @@ -72,11 +65,43 @@ func figureOutConfigDir() (configFolder string) { } func mainImpl() error { + log.SetLevel(log.Lvl(*logLevel)) + + exePath, err := os.Executable() + if err != nil { + return fmt.Errorf("failed to determine kanata-tray path: %v", err) + } + exePath, err = filepath.EvalSymlinks(exePath) + if err != nil { + return fmt.Errorf("failed to eval symlinks: %v", err) + } + exeDir := filepath.Dir(exePath) + const logFilename string = "kanata_tray_lastrun.log" + logFilepath := filepath.Join(exeDir, logFilename) + logFile, err := os.Create(logFilepath) + if err != nil { + return fmt.Errorf("failed to create %s file: %v", logFilename, err) + } + // Check if stderr is available. Specifically it won't be, when running + // Windows binary compiled with -H=windowsgui ldflag. + _, err = os.Stderr.Stat() + if err != nil { + log.SetOutput(logFile) + } else { + log.SetOutput(io.MultiWriter(logFile, os.Stderr)) + } + + if int(*logLevel) <= int(log.DEBUG) { + log.SetHeader(`${time_rfc3339_nano} ${level} ${short_file}:${line}`) + } else { + log.SetHeader(`${time_rfc3339_nano} ${level}`) + } + configFolder := figureOutConfigDir() log.Infof("kanata-tray config folder: %s", configFolder) - err := os.MkdirAll(filepath.Join(configFolder, "icons"), os.ModePerm) + err = os.MkdirAll(filepath.Join(configFolder, "icons"), os.ModePerm) if err != nil { return fmt.Errorf("failed to create folder: %v", err) } @@ -94,7 +119,7 @@ func mainImpl() error { runner := runner.NewRunner() onReady := func() { - app := app.NewSystrayApp(menuTemplate, layerIcons, cfg.General.AllowConcurrentPresets) + app := app.NewSystrayApp(menuTemplate, layerIcons, cfg.General.AllowConcurrentPresets, logFilepath) go app.StartProcessingLoop(runner, configFolder) }