Files
netbird/client/ui/uilogpath.go
Zoltán Papp ff6aef5e2a feat(ui): GUI debug logging follows daemon log level + debug bundle
When the daemon is set to debug/trace, the GUI now automatically writes a
rotated gui-client.log in the user's config dir and the daemon's debug bundle
collects it. The UI learns the level both at startup (daemon already in debug)
and live, by piggybacking the existing SubscribeEvents stream: the daemon
publishes a marked log-level-changed SystemEvent (and a per-subscription
snapshot), which DaemonFeed routes to guilog.DebugLog instead of an OS toast.
The UI registers its log path via a new RegisterUILog RPC so the root daemon,
which can't resolve the user's config dir, knows where to find the file.

Manual --log-file (any value) disables the daemon-driven file logging.

Fix: client/ui SetLogLevel looked up proto.LogLevel_value with the lowercase
logrus name, which never matched the uppercase enum keys and silently fell back
to INFO — so trace/debug requests from the bundle flow had no effect.
2026-06-11 18:34:48 +02:00

42 lines
1.3 KiB
Go

//go:build !android && !ios && !freebsd && !js
package main
import (
"os"
"path/filepath"
log "github.com/sirupsen/logrus"
"github.com/netbirdio/netbird/client/ui/guilog"
)
// uiLogFileName is the base name of the GUI's log. Rotated siblings
// (gui-client.log.*, *.gz) share the prefix; the daemon's debug bundle globs
// "gui-client*.log.*" to collect them (see addUILog in client/internal/debug).
const uiLogFileName = "gui-client.log"
// uiLogPath resolves os.UserConfigDir()/netbird/gui-client.log — the per-OS-user
// path the GUI writes its log to while the daemon is in debug, and the path it
// registers with the daemon for debug-bundle collection. Native separators are
// preserved (the daemon os.Open()s this path).
func uiLogPath() (string, error) {
dir, err := os.UserConfigDir()
if err != nil {
return "", err
}
return filepath.Join(dir, "netbird", uiLogFileName), nil
}
// newDebugLog builds the GUI debug log. userSetLogFile disables it (manual
// --log-file override). If the config dir can't be resolved it's created
// disabled, so the GUI keeps working without file logging.
func newDebugLog(userSetLogFile bool) *guilog.DebugLog {
path, err := uiLogPath()
if err != nil {
log.Warnf("resolve GUI log path: %v; GUI file logging disabled", err)
return guilog.NewDebugLog("", false)
}
return guilog.NewDebugLog(path, !userSetLogFile)
}