diff --git a/client/internal/debug/debug.go b/client/internal/debug/debug.go index 9ab18dd80..db8f33955 100644 --- a/client/internal/debug/debug.go +++ b/client/internal/debug/debug.go @@ -229,9 +229,16 @@ scutil_dns.txt (macOS only): const ( clientLogFile = "client.log" + uiLogFile = "gui-client.log" errorLogFile = "netbird.err" stdoutLogFile = "netbird.out" + // Rotated-log glob prefixes (base log name without extension) passed to + // addRotatedLogFiles. The daemon's own log and the GUI log live in the same + // dir, so the prefixes must be disjoint to keep their rotated siblings apart. + clientLogPrefix = "client" + uiLogPrefix = "gui-client" + darwinErrorLogPath = "/var/log/netbird.out.log" darwinStdoutLogPath = "/var/log/netbird.err.log" ) @@ -249,6 +256,7 @@ type BundleGenerator struct { statusRecorder *peer.Status syncResponse *mgmProto.SyncResponse logPath string + uiLogPath string tempDir string cpuProfile []byte capturePath string @@ -275,6 +283,7 @@ type GeneratorDependencies struct { StatusRecorder *peer.Status SyncResponse *mgmProto.SyncResponse LogPath string + UILogPath string // Absolute path to the desktop UI's gui-client.log, reported via RegisterUILog. Empty if no UI registered one. TempDir string // Directory for temporary bundle zip files. If empty, os.TempDir() is used. CPUProfile []byte CapturePath string @@ -298,6 +307,7 @@ func NewBundleGenerator(deps GeneratorDependencies, cfg BundleConfig) *BundleGen statusRecorder: deps.StatusRecorder, syncResponse: deps.SyncResponse, logPath: deps.LogPath, + uiLogPath: deps.UILogPath, tempDir: deps.TempDir, cpuProfile: deps.CPUProfile, capturePath: deps.CapturePath, @@ -408,6 +418,10 @@ func (g *BundleGenerator) createArchive() error { log.Errorf("failed to add logs to debug bundle: %v", err) } + if err := g.addUILog(); err != nil { + log.Errorf("failed to add UI log to debug bundle: %v", err) + } + if err := g.addUpdateLogs(); err != nil { log.Errorf("failed to add updater logs: %v", err) } @@ -972,7 +986,7 @@ func (g *BundleGenerator) addLogfile() error { return fmt.Errorf("add client log file to zip: %w", err) } - g.addRotatedLogFiles(logDir) + g.addRotatedLogFiles(logDir, clientLogPrefix) stdErrLogPath := filepath.Join(logDir, errorLogFile) stdoutLogPath := filepath.Join(logDir, stdoutLogFile) @@ -992,6 +1006,25 @@ func (g *BundleGenerator) addLogfile() error { return nil } +// addUILog adds the desktop UI's gui-client.log (and its rotated siblings) to +// the bundle. The path is reported by the UI via RegisterUILog; empty when no +// UI registered one (e.g. headless / server). Missing file is non-fatal — the +// UI only writes it while the daemon is in debug, so it's often absent. +func (g *BundleGenerator) addUILog() error { + if g.uiLogPath == "" { + log.Debugf("no UI log path registered, skipping in debug bundle") + return nil + } + + if err := g.addSingleLogfile(g.uiLogPath, uiLogFile); err != nil { + return fmt.Errorf("add UI log file to zip: %w", err) + } + + g.addRotatedLogFiles(filepath.Dir(g.uiLogPath), uiLogPrefix) + + return nil +} + // addSingleLogfile adds a single log file to the archive func (g *BundleGenerator) addSingleLogfile(logPath, targetName string) error { logFile, err := os.Open(logPath) @@ -1064,14 +1097,16 @@ func (g *BundleGenerator) addSingleLogFileGz(logPath, targetName string) error { return nil } -// addRotatedLogFiles adds rotated log files to the bundle based on logFileCount -func (g *BundleGenerator) addRotatedLogFiles(logDir string) { +// addRotatedLogFiles adds rotated log files to the bundle based on logFileCount. +// prefix is the base log name without extension (e.g. "client", "gui-client"); +// the glob matches both files rotated by us and by logrotate on linux. +func (g *BundleGenerator) addRotatedLogFiles(logDir, prefix string) { if g.logFileCount == 0 { return } - // This regex will match both logs rotated by us and logrotate on linux - pattern := filepath.Join(logDir, "client*.log.*") + // This pattern matches both logs rotated by us and logrotate on linux + pattern := filepath.Join(logDir, prefix+"*.log.*") files, err := filepath.Glob(pattern) if err != nil { log.Warnf("failed to glob rotated logs: %v", err) diff --git a/client/internal/debug/debug_logfiles_test.go b/client/internal/debug/debug_logfiles_test.go index f6473f979..3749b3e9b 100644 --- a/client/internal/debug/debug_logfiles_test.go +++ b/client/internal/debug/debug_logfiles_test.go @@ -40,6 +40,25 @@ func TestAddRotatedLogFiles_PicksUpAllVariants(t *testing.T) { require.NotContains(t, names, "other.log", "unrelated files should not be in bundle") } +// TestAddRotatedLogFiles_GUIPrefix asserts the prefix parameter scopes the glob +// to the GUI log: gui-client.log.* rotated siblings are picked up and the +// daemon's own client.log.* are not (and vice versa, covered above). This is +// the load-bearing check for the gui-client.log bundle collection — the old +// "client*.log.*" glob would have missed gui-client rotations. +func TestAddRotatedLogFiles_GUIPrefix(t *testing.T) { + dir := t.TempDir() + + writeFile(t, filepath.Join(dir, "gui-client.log.1"), "gui rotated\n") + writeGzFile(t, filepath.Join(dir, "gui-client.log.2.gz"), "gui rotated gz\n") + writeFile(t, filepath.Join(dir, "client.log.1"), "daemon rotated\n") + + names := runAddRotatedLogFilesPrefix(t, dir, "gui-client", 10) + + require.Contains(t, names, "gui-client.log.1", "gui-client rotated file should be in bundle") + require.Contains(t, names, "gui-client.log.2.gz", "gui-client gz rotated file should be in bundle") + require.NotContains(t, names, "client.log.1", "daemon rotated file must not match the gui-client prefix") +} + // TestAddRotatedLogFiles_RespectsLogFileCount asserts that only the newest // logFileCount rotated files are bundled, ordered by mtime. func TestAddRotatedLogFiles_RespectsLogFileCount(t *testing.T) { @@ -67,6 +86,10 @@ func TestAddRotatedLogFiles_RespectsLogFileCount(t *testing.T) { // runAddRotatedLogFiles calls addRotatedLogFiles against a fresh in-memory // zip writer and returns the set of entry names that ended up in the archive. func runAddRotatedLogFiles(t *testing.T, dir string, logFileCount uint32) map[string]struct{} { + return runAddRotatedLogFilesPrefix(t, dir, "client", logFileCount) +} + +func runAddRotatedLogFilesPrefix(t *testing.T, dir, prefix string, logFileCount uint32) map[string]struct{} { t.Helper() var buf bytes.Buffer @@ -74,7 +97,7 @@ func runAddRotatedLogFiles(t *testing.T, dir string, logFileCount uint32) map[st archive: zip.NewWriter(&buf), logFileCount: logFileCount, } - g.addRotatedLogFiles(dir) + g.addRotatedLogFiles(dir, prefix) require.NoError(t, g.archive.Close()) zr, err := zip.NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len())) diff --git a/client/proto/daemon.pb.go b/client/proto/daemon.pb.go index dfc3e3340..6286cbe91 100644 --- a/client/proto/daemon.pb.go +++ b/client/proto/daemon.pb.go @@ -192,7 +192,7 @@ func (x SystemEvent_Severity) Number() protoreflect.EnumNumber { // Deprecated: Use SystemEvent_Severity.Descriptor instead. func (SystemEvent_Severity) EnumDescriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{51, 0} + return file_daemon_proto_rawDescGZIP(), []int{53, 0} } type SystemEvent_Category int32 @@ -247,7 +247,7 @@ func (x SystemEvent_Category) Number() protoreflect.EnumNumber { // Deprecated: Use SystemEvent_Category.Descriptor instead. func (SystemEvent_Category) EnumDescriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{51, 1} + return file_daemon_proto_rawDescGZIP(), []int{53, 1} } type EmptyRequest struct { @@ -3043,6 +3043,86 @@ func (*SetLogLevelResponse) Descriptor() ([]byte, []int) { return file_daemon_proto_rawDescGZIP(), []int{36} } +type RegisterUILogRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RegisterUILogRequest) Reset() { + *x = RegisterUILogRequest{} + mi := &file_daemon_proto_msgTypes[37] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RegisterUILogRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterUILogRequest) ProtoMessage() {} + +func (x *RegisterUILogRequest) ProtoReflect() protoreflect.Message { + mi := &file_daemon_proto_msgTypes[37] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegisterUILogRequest.ProtoReflect.Descriptor instead. +func (*RegisterUILogRequest) Descriptor() ([]byte, []int) { + return file_daemon_proto_rawDescGZIP(), []int{37} +} + +func (x *RegisterUILogRequest) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +type RegisterUILogResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RegisterUILogResponse) Reset() { + *x = RegisterUILogResponse{} + mi := &file_daemon_proto_msgTypes[38] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RegisterUILogResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterUILogResponse) ProtoMessage() {} + +func (x *RegisterUILogResponse) ProtoReflect() protoreflect.Message { + mi := &file_daemon_proto_msgTypes[38] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegisterUILogResponse.ProtoReflect.Descriptor instead. +func (*RegisterUILogResponse) Descriptor() ([]byte, []int) { + return file_daemon_proto_rawDescGZIP(), []int{38} +} + // State represents a daemon state entry type State struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -3053,7 +3133,7 @@ type State struct { func (x *State) Reset() { *x = State{} - mi := &file_daemon_proto_msgTypes[37] + mi := &file_daemon_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3065,7 +3145,7 @@ func (x *State) String() string { func (*State) ProtoMessage() {} func (x *State) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[37] + mi := &file_daemon_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3078,7 +3158,7 @@ func (x *State) ProtoReflect() protoreflect.Message { // Deprecated: Use State.ProtoReflect.Descriptor instead. func (*State) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{37} + return file_daemon_proto_rawDescGZIP(), []int{39} } func (x *State) GetName() string { @@ -3097,7 +3177,7 @@ type ListStatesRequest struct { func (x *ListStatesRequest) Reset() { *x = ListStatesRequest{} - mi := &file_daemon_proto_msgTypes[38] + mi := &file_daemon_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3109,7 +3189,7 @@ func (x *ListStatesRequest) String() string { func (*ListStatesRequest) ProtoMessage() {} func (x *ListStatesRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[38] + mi := &file_daemon_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3122,7 +3202,7 @@ func (x *ListStatesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListStatesRequest.ProtoReflect.Descriptor instead. func (*ListStatesRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{38} + return file_daemon_proto_rawDescGZIP(), []int{40} } // ListStatesResponse contains a list of states @@ -3135,7 +3215,7 @@ type ListStatesResponse struct { func (x *ListStatesResponse) Reset() { *x = ListStatesResponse{} - mi := &file_daemon_proto_msgTypes[39] + mi := &file_daemon_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3147,7 +3227,7 @@ func (x *ListStatesResponse) String() string { func (*ListStatesResponse) ProtoMessage() {} func (x *ListStatesResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[39] + mi := &file_daemon_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3160,7 +3240,7 @@ func (x *ListStatesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListStatesResponse.ProtoReflect.Descriptor instead. func (*ListStatesResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{39} + return file_daemon_proto_rawDescGZIP(), []int{41} } func (x *ListStatesResponse) GetStates() []*State { @@ -3181,7 +3261,7 @@ type CleanStateRequest struct { func (x *CleanStateRequest) Reset() { *x = CleanStateRequest{} - mi := &file_daemon_proto_msgTypes[40] + mi := &file_daemon_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3193,7 +3273,7 @@ func (x *CleanStateRequest) String() string { func (*CleanStateRequest) ProtoMessage() {} func (x *CleanStateRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[40] + mi := &file_daemon_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3206,7 +3286,7 @@ func (x *CleanStateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CleanStateRequest.ProtoReflect.Descriptor instead. func (*CleanStateRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{40} + return file_daemon_proto_rawDescGZIP(), []int{42} } func (x *CleanStateRequest) GetStateName() string { @@ -3233,7 +3313,7 @@ type CleanStateResponse struct { func (x *CleanStateResponse) Reset() { *x = CleanStateResponse{} - mi := &file_daemon_proto_msgTypes[41] + mi := &file_daemon_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3245,7 +3325,7 @@ func (x *CleanStateResponse) String() string { func (*CleanStateResponse) ProtoMessage() {} func (x *CleanStateResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[41] + mi := &file_daemon_proto_msgTypes[43] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3258,7 +3338,7 @@ func (x *CleanStateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CleanStateResponse.ProtoReflect.Descriptor instead. func (*CleanStateResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{41} + return file_daemon_proto_rawDescGZIP(), []int{43} } func (x *CleanStateResponse) GetCleanedStates() int32 { @@ -3279,7 +3359,7 @@ type DeleteStateRequest struct { func (x *DeleteStateRequest) Reset() { *x = DeleteStateRequest{} - mi := &file_daemon_proto_msgTypes[42] + mi := &file_daemon_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3291,7 +3371,7 @@ func (x *DeleteStateRequest) String() string { func (*DeleteStateRequest) ProtoMessage() {} func (x *DeleteStateRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[42] + mi := &file_daemon_proto_msgTypes[44] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3304,7 +3384,7 @@ func (x *DeleteStateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteStateRequest.ProtoReflect.Descriptor instead. func (*DeleteStateRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{42} + return file_daemon_proto_rawDescGZIP(), []int{44} } func (x *DeleteStateRequest) GetStateName() string { @@ -3331,7 +3411,7 @@ type DeleteStateResponse struct { func (x *DeleteStateResponse) Reset() { *x = DeleteStateResponse{} - mi := &file_daemon_proto_msgTypes[43] + mi := &file_daemon_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3343,7 +3423,7 @@ func (x *DeleteStateResponse) String() string { func (*DeleteStateResponse) ProtoMessage() {} func (x *DeleteStateResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[43] + mi := &file_daemon_proto_msgTypes[45] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3356,7 +3436,7 @@ func (x *DeleteStateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteStateResponse.ProtoReflect.Descriptor instead. func (*DeleteStateResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{43} + return file_daemon_proto_rawDescGZIP(), []int{45} } func (x *DeleteStateResponse) GetDeletedStates() int32 { @@ -3375,7 +3455,7 @@ type SetSyncResponsePersistenceRequest struct { func (x *SetSyncResponsePersistenceRequest) Reset() { *x = SetSyncResponsePersistenceRequest{} - mi := &file_daemon_proto_msgTypes[44] + mi := &file_daemon_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3387,7 +3467,7 @@ func (x *SetSyncResponsePersistenceRequest) String() string { func (*SetSyncResponsePersistenceRequest) ProtoMessage() {} func (x *SetSyncResponsePersistenceRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[44] + mi := &file_daemon_proto_msgTypes[46] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3400,7 +3480,7 @@ func (x *SetSyncResponsePersistenceRequest) ProtoReflect() protoreflect.Message // Deprecated: Use SetSyncResponsePersistenceRequest.ProtoReflect.Descriptor instead. func (*SetSyncResponsePersistenceRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{44} + return file_daemon_proto_rawDescGZIP(), []int{46} } func (x *SetSyncResponsePersistenceRequest) GetEnabled() bool { @@ -3418,7 +3498,7 @@ type SetSyncResponsePersistenceResponse struct { func (x *SetSyncResponsePersistenceResponse) Reset() { *x = SetSyncResponsePersistenceResponse{} - mi := &file_daemon_proto_msgTypes[45] + mi := &file_daemon_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3430,7 +3510,7 @@ func (x *SetSyncResponsePersistenceResponse) String() string { func (*SetSyncResponsePersistenceResponse) ProtoMessage() {} func (x *SetSyncResponsePersistenceResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[45] + mi := &file_daemon_proto_msgTypes[47] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3443,7 +3523,7 @@ func (x *SetSyncResponsePersistenceResponse) ProtoReflect() protoreflect.Message // Deprecated: Use SetSyncResponsePersistenceResponse.ProtoReflect.Descriptor instead. func (*SetSyncResponsePersistenceResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{45} + return file_daemon_proto_rawDescGZIP(), []int{47} } type TCPFlags struct { @@ -3460,7 +3540,7 @@ type TCPFlags struct { func (x *TCPFlags) Reset() { *x = TCPFlags{} - mi := &file_daemon_proto_msgTypes[46] + mi := &file_daemon_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3472,7 +3552,7 @@ func (x *TCPFlags) String() string { func (*TCPFlags) ProtoMessage() {} func (x *TCPFlags) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[46] + mi := &file_daemon_proto_msgTypes[48] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3485,7 +3565,7 @@ func (x *TCPFlags) ProtoReflect() protoreflect.Message { // Deprecated: Use TCPFlags.ProtoReflect.Descriptor instead. func (*TCPFlags) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{46} + return file_daemon_proto_rawDescGZIP(), []int{48} } func (x *TCPFlags) GetSyn() bool { @@ -3547,7 +3627,7 @@ type TracePacketRequest struct { func (x *TracePacketRequest) Reset() { *x = TracePacketRequest{} - mi := &file_daemon_proto_msgTypes[47] + mi := &file_daemon_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3559,7 +3639,7 @@ func (x *TracePacketRequest) String() string { func (*TracePacketRequest) ProtoMessage() {} func (x *TracePacketRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[47] + mi := &file_daemon_proto_msgTypes[49] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3572,7 +3652,7 @@ func (x *TracePacketRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use TracePacketRequest.ProtoReflect.Descriptor instead. func (*TracePacketRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{47} + return file_daemon_proto_rawDescGZIP(), []int{49} } func (x *TracePacketRequest) GetSourceIp() string { @@ -3650,7 +3730,7 @@ type TraceStage struct { func (x *TraceStage) Reset() { *x = TraceStage{} - mi := &file_daemon_proto_msgTypes[48] + mi := &file_daemon_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3662,7 +3742,7 @@ func (x *TraceStage) String() string { func (*TraceStage) ProtoMessage() {} func (x *TraceStage) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[48] + mi := &file_daemon_proto_msgTypes[50] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3675,7 +3755,7 @@ func (x *TraceStage) ProtoReflect() protoreflect.Message { // Deprecated: Use TraceStage.ProtoReflect.Descriptor instead. func (*TraceStage) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{48} + return file_daemon_proto_rawDescGZIP(), []int{50} } func (x *TraceStage) GetName() string { @@ -3716,7 +3796,7 @@ type TracePacketResponse struct { func (x *TracePacketResponse) Reset() { *x = TracePacketResponse{} - mi := &file_daemon_proto_msgTypes[49] + mi := &file_daemon_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3728,7 +3808,7 @@ func (x *TracePacketResponse) String() string { func (*TracePacketResponse) ProtoMessage() {} func (x *TracePacketResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[49] + mi := &file_daemon_proto_msgTypes[51] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3741,7 +3821,7 @@ func (x *TracePacketResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use TracePacketResponse.ProtoReflect.Descriptor instead. func (*TracePacketResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{49} + return file_daemon_proto_rawDescGZIP(), []int{51} } func (x *TracePacketResponse) GetStages() []*TraceStage { @@ -3766,7 +3846,7 @@ type SubscribeRequest struct { func (x *SubscribeRequest) Reset() { *x = SubscribeRequest{} - mi := &file_daemon_proto_msgTypes[50] + mi := &file_daemon_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3778,7 +3858,7 @@ func (x *SubscribeRequest) String() string { func (*SubscribeRequest) ProtoMessage() {} func (x *SubscribeRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[50] + mi := &file_daemon_proto_msgTypes[52] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3791,7 +3871,7 @@ func (x *SubscribeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SubscribeRequest.ProtoReflect.Descriptor instead. func (*SubscribeRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{50} + return file_daemon_proto_rawDescGZIP(), []int{52} } type SystemEvent struct { @@ -3809,7 +3889,7 @@ type SystemEvent struct { func (x *SystemEvent) Reset() { *x = SystemEvent{} - mi := &file_daemon_proto_msgTypes[51] + mi := &file_daemon_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3821,7 +3901,7 @@ func (x *SystemEvent) String() string { func (*SystemEvent) ProtoMessage() {} func (x *SystemEvent) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[51] + mi := &file_daemon_proto_msgTypes[53] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3834,7 +3914,7 @@ func (x *SystemEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use SystemEvent.ProtoReflect.Descriptor instead. func (*SystemEvent) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{51} + return file_daemon_proto_rawDescGZIP(), []int{53} } func (x *SystemEvent) GetId() string { @@ -3894,7 +3974,7 @@ type GetEventsRequest struct { func (x *GetEventsRequest) Reset() { *x = GetEventsRequest{} - mi := &file_daemon_proto_msgTypes[52] + mi := &file_daemon_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3906,7 +3986,7 @@ func (x *GetEventsRequest) String() string { func (*GetEventsRequest) ProtoMessage() {} func (x *GetEventsRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[52] + mi := &file_daemon_proto_msgTypes[54] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3919,7 +3999,7 @@ func (x *GetEventsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetEventsRequest.ProtoReflect.Descriptor instead. func (*GetEventsRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{52} + return file_daemon_proto_rawDescGZIP(), []int{54} } type GetEventsResponse struct { @@ -3931,7 +4011,7 @@ type GetEventsResponse struct { func (x *GetEventsResponse) Reset() { *x = GetEventsResponse{} - mi := &file_daemon_proto_msgTypes[53] + mi := &file_daemon_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3943,7 +4023,7 @@ func (x *GetEventsResponse) String() string { func (*GetEventsResponse) ProtoMessage() {} func (x *GetEventsResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[53] + mi := &file_daemon_proto_msgTypes[55] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3956,7 +4036,7 @@ func (x *GetEventsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetEventsResponse.ProtoReflect.Descriptor instead. func (*GetEventsResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{53} + return file_daemon_proto_rawDescGZIP(), []int{55} } func (x *GetEventsResponse) GetEvents() []*SystemEvent { @@ -3976,7 +4056,7 @@ type SwitchProfileRequest struct { func (x *SwitchProfileRequest) Reset() { *x = SwitchProfileRequest{} - mi := &file_daemon_proto_msgTypes[54] + mi := &file_daemon_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3988,7 +4068,7 @@ func (x *SwitchProfileRequest) String() string { func (*SwitchProfileRequest) ProtoMessage() {} func (x *SwitchProfileRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[54] + mi := &file_daemon_proto_msgTypes[56] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4001,7 +4081,7 @@ func (x *SwitchProfileRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SwitchProfileRequest.ProtoReflect.Descriptor instead. func (*SwitchProfileRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{54} + return file_daemon_proto_rawDescGZIP(), []int{56} } func (x *SwitchProfileRequest) GetProfileName() string { @@ -4026,7 +4106,7 @@ type SwitchProfileResponse struct { func (x *SwitchProfileResponse) Reset() { *x = SwitchProfileResponse{} - mi := &file_daemon_proto_msgTypes[55] + mi := &file_daemon_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4038,7 +4118,7 @@ func (x *SwitchProfileResponse) String() string { func (*SwitchProfileResponse) ProtoMessage() {} func (x *SwitchProfileResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[55] + mi := &file_daemon_proto_msgTypes[57] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4051,7 +4131,7 @@ func (x *SwitchProfileResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SwitchProfileResponse.ProtoReflect.Descriptor instead. func (*SwitchProfileResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{55} + return file_daemon_proto_rawDescGZIP(), []int{57} } type SetConfigRequest struct { @@ -4100,7 +4180,7 @@ type SetConfigRequest struct { func (x *SetConfigRequest) Reset() { *x = SetConfigRequest{} - mi := &file_daemon_proto_msgTypes[56] + mi := &file_daemon_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4112,7 +4192,7 @@ func (x *SetConfigRequest) String() string { func (*SetConfigRequest) ProtoMessage() {} func (x *SetConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[56] + mi := &file_daemon_proto_msgTypes[58] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4125,7 +4205,7 @@ func (x *SetConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetConfigRequest.ProtoReflect.Descriptor instead. func (*SetConfigRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{56} + return file_daemon_proto_rawDescGZIP(), []int{58} } func (x *SetConfigRequest) GetUsername() string { @@ -4381,7 +4461,7 @@ type SetConfigResponse struct { func (x *SetConfigResponse) Reset() { *x = SetConfigResponse{} - mi := &file_daemon_proto_msgTypes[57] + mi := &file_daemon_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4393,7 +4473,7 @@ func (x *SetConfigResponse) String() string { func (*SetConfigResponse) ProtoMessage() {} func (x *SetConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[57] + mi := &file_daemon_proto_msgTypes[59] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4406,7 +4486,7 @@ func (x *SetConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetConfigResponse.ProtoReflect.Descriptor instead. func (*SetConfigResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{57} + return file_daemon_proto_rawDescGZIP(), []int{59} } type AddProfileRequest struct { @@ -4419,7 +4499,7 @@ type AddProfileRequest struct { func (x *AddProfileRequest) Reset() { *x = AddProfileRequest{} - mi := &file_daemon_proto_msgTypes[58] + mi := &file_daemon_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4431,7 +4511,7 @@ func (x *AddProfileRequest) String() string { func (*AddProfileRequest) ProtoMessage() {} func (x *AddProfileRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[58] + mi := &file_daemon_proto_msgTypes[60] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4444,7 +4524,7 @@ func (x *AddProfileRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AddProfileRequest.ProtoReflect.Descriptor instead. func (*AddProfileRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{58} + return file_daemon_proto_rawDescGZIP(), []int{60} } func (x *AddProfileRequest) GetUsername() string { @@ -4469,7 +4549,7 @@ type AddProfileResponse struct { func (x *AddProfileResponse) Reset() { *x = AddProfileResponse{} - mi := &file_daemon_proto_msgTypes[59] + mi := &file_daemon_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4481,7 +4561,7 @@ func (x *AddProfileResponse) String() string { func (*AddProfileResponse) ProtoMessage() {} func (x *AddProfileResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[59] + mi := &file_daemon_proto_msgTypes[61] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4494,7 +4574,7 @@ func (x *AddProfileResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AddProfileResponse.ProtoReflect.Descriptor instead. func (*AddProfileResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{59} + return file_daemon_proto_rawDescGZIP(), []int{61} } type RemoveProfileRequest struct { @@ -4507,7 +4587,7 @@ type RemoveProfileRequest struct { func (x *RemoveProfileRequest) Reset() { *x = RemoveProfileRequest{} - mi := &file_daemon_proto_msgTypes[60] + mi := &file_daemon_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4519,7 +4599,7 @@ func (x *RemoveProfileRequest) String() string { func (*RemoveProfileRequest) ProtoMessage() {} func (x *RemoveProfileRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[60] + mi := &file_daemon_proto_msgTypes[62] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4532,7 +4612,7 @@ func (x *RemoveProfileRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveProfileRequest.ProtoReflect.Descriptor instead. func (*RemoveProfileRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{60} + return file_daemon_proto_rawDescGZIP(), []int{62} } func (x *RemoveProfileRequest) GetUsername() string { @@ -4557,7 +4637,7 @@ type RemoveProfileResponse struct { func (x *RemoveProfileResponse) Reset() { *x = RemoveProfileResponse{} - mi := &file_daemon_proto_msgTypes[61] + mi := &file_daemon_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4569,7 +4649,7 @@ func (x *RemoveProfileResponse) String() string { func (*RemoveProfileResponse) ProtoMessage() {} func (x *RemoveProfileResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[61] + mi := &file_daemon_proto_msgTypes[63] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4582,7 +4662,7 @@ func (x *RemoveProfileResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveProfileResponse.ProtoReflect.Descriptor instead. func (*RemoveProfileResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{61} + return file_daemon_proto_rawDescGZIP(), []int{63} } type ListProfilesRequest struct { @@ -4594,7 +4674,7 @@ type ListProfilesRequest struct { func (x *ListProfilesRequest) Reset() { *x = ListProfilesRequest{} - mi := &file_daemon_proto_msgTypes[62] + mi := &file_daemon_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4606,7 +4686,7 @@ func (x *ListProfilesRequest) String() string { func (*ListProfilesRequest) ProtoMessage() {} func (x *ListProfilesRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[62] + mi := &file_daemon_proto_msgTypes[64] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4619,7 +4699,7 @@ func (x *ListProfilesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListProfilesRequest.ProtoReflect.Descriptor instead. func (*ListProfilesRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{62} + return file_daemon_proto_rawDescGZIP(), []int{64} } func (x *ListProfilesRequest) GetUsername() string { @@ -4638,7 +4718,7 @@ type ListProfilesResponse struct { func (x *ListProfilesResponse) Reset() { *x = ListProfilesResponse{} - mi := &file_daemon_proto_msgTypes[63] + mi := &file_daemon_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4650,7 +4730,7 @@ func (x *ListProfilesResponse) String() string { func (*ListProfilesResponse) ProtoMessage() {} func (x *ListProfilesResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[63] + mi := &file_daemon_proto_msgTypes[65] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4663,7 +4743,7 @@ func (x *ListProfilesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListProfilesResponse.ProtoReflect.Descriptor instead. func (*ListProfilesResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{63} + return file_daemon_proto_rawDescGZIP(), []int{65} } func (x *ListProfilesResponse) GetProfiles() []*Profile { @@ -4683,7 +4763,7 @@ type Profile struct { func (x *Profile) Reset() { *x = Profile{} - mi := &file_daemon_proto_msgTypes[64] + mi := &file_daemon_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4695,7 +4775,7 @@ func (x *Profile) String() string { func (*Profile) ProtoMessage() {} func (x *Profile) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[64] + mi := &file_daemon_proto_msgTypes[66] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4708,7 +4788,7 @@ func (x *Profile) ProtoReflect() protoreflect.Message { // Deprecated: Use Profile.ProtoReflect.Descriptor instead. func (*Profile) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{64} + return file_daemon_proto_rawDescGZIP(), []int{66} } func (x *Profile) GetName() string { @@ -4733,7 +4813,7 @@ type GetActiveProfileRequest struct { func (x *GetActiveProfileRequest) Reset() { *x = GetActiveProfileRequest{} - mi := &file_daemon_proto_msgTypes[65] + mi := &file_daemon_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4745,7 +4825,7 @@ func (x *GetActiveProfileRequest) String() string { func (*GetActiveProfileRequest) ProtoMessage() {} func (x *GetActiveProfileRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[65] + mi := &file_daemon_proto_msgTypes[67] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4758,7 +4838,7 @@ func (x *GetActiveProfileRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetActiveProfileRequest.ProtoReflect.Descriptor instead. func (*GetActiveProfileRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{65} + return file_daemon_proto_rawDescGZIP(), []int{67} } type GetActiveProfileResponse struct { @@ -4771,7 +4851,7 @@ type GetActiveProfileResponse struct { func (x *GetActiveProfileResponse) Reset() { *x = GetActiveProfileResponse{} - mi := &file_daemon_proto_msgTypes[66] + mi := &file_daemon_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4783,7 +4863,7 @@ func (x *GetActiveProfileResponse) String() string { func (*GetActiveProfileResponse) ProtoMessage() {} func (x *GetActiveProfileResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[66] + mi := &file_daemon_proto_msgTypes[68] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4796,7 +4876,7 @@ func (x *GetActiveProfileResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetActiveProfileResponse.ProtoReflect.Descriptor instead. func (*GetActiveProfileResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{66} + return file_daemon_proto_rawDescGZIP(), []int{68} } func (x *GetActiveProfileResponse) GetProfileName() string { @@ -4823,7 +4903,7 @@ type LogoutRequest struct { func (x *LogoutRequest) Reset() { *x = LogoutRequest{} - mi := &file_daemon_proto_msgTypes[67] + mi := &file_daemon_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4835,7 +4915,7 @@ func (x *LogoutRequest) String() string { func (*LogoutRequest) ProtoMessage() {} func (x *LogoutRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[67] + mi := &file_daemon_proto_msgTypes[69] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4848,7 +4928,7 @@ func (x *LogoutRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use LogoutRequest.ProtoReflect.Descriptor instead. func (*LogoutRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{67} + return file_daemon_proto_rawDescGZIP(), []int{69} } func (x *LogoutRequest) GetProfileName() string { @@ -4873,7 +4953,7 @@ type LogoutResponse struct { func (x *LogoutResponse) Reset() { *x = LogoutResponse{} - mi := &file_daemon_proto_msgTypes[68] + mi := &file_daemon_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4885,7 +4965,7 @@ func (x *LogoutResponse) String() string { func (*LogoutResponse) ProtoMessage() {} func (x *LogoutResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[68] + mi := &file_daemon_proto_msgTypes[70] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4898,7 +4978,7 @@ func (x *LogoutResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use LogoutResponse.ProtoReflect.Descriptor instead. func (*LogoutResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{68} + return file_daemon_proto_rawDescGZIP(), []int{70} } type GetFeaturesRequest struct { @@ -4909,7 +4989,7 @@ type GetFeaturesRequest struct { func (x *GetFeaturesRequest) Reset() { *x = GetFeaturesRequest{} - mi := &file_daemon_proto_msgTypes[69] + mi := &file_daemon_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4921,7 +5001,7 @@ func (x *GetFeaturesRequest) String() string { func (*GetFeaturesRequest) ProtoMessage() {} func (x *GetFeaturesRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[69] + mi := &file_daemon_proto_msgTypes[71] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4934,7 +5014,7 @@ func (x *GetFeaturesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetFeaturesRequest.ProtoReflect.Descriptor instead. func (*GetFeaturesRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{69} + return file_daemon_proto_rawDescGZIP(), []int{71} } type GetFeaturesResponse struct { @@ -4948,7 +5028,7 @@ type GetFeaturesResponse struct { func (x *GetFeaturesResponse) Reset() { *x = GetFeaturesResponse{} - mi := &file_daemon_proto_msgTypes[70] + mi := &file_daemon_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4960,7 +5040,7 @@ func (x *GetFeaturesResponse) String() string { func (*GetFeaturesResponse) ProtoMessage() {} func (x *GetFeaturesResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[70] + mi := &file_daemon_proto_msgTypes[72] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4973,7 +5053,7 @@ func (x *GetFeaturesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetFeaturesResponse.ProtoReflect.Descriptor instead. func (*GetFeaturesResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{70} + return file_daemon_proto_rawDescGZIP(), []int{72} } func (x *GetFeaturesResponse) GetDisableProfiles() bool { @@ -5005,7 +5085,7 @@ type TriggerUpdateRequest struct { func (x *TriggerUpdateRequest) Reset() { *x = TriggerUpdateRequest{} - mi := &file_daemon_proto_msgTypes[71] + mi := &file_daemon_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5017,7 +5097,7 @@ func (x *TriggerUpdateRequest) String() string { func (*TriggerUpdateRequest) ProtoMessage() {} func (x *TriggerUpdateRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[71] + mi := &file_daemon_proto_msgTypes[73] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5030,7 +5110,7 @@ func (x *TriggerUpdateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use TriggerUpdateRequest.ProtoReflect.Descriptor instead. func (*TriggerUpdateRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{71} + return file_daemon_proto_rawDescGZIP(), []int{73} } type TriggerUpdateResponse struct { @@ -5043,7 +5123,7 @@ type TriggerUpdateResponse struct { func (x *TriggerUpdateResponse) Reset() { *x = TriggerUpdateResponse{} - mi := &file_daemon_proto_msgTypes[72] + mi := &file_daemon_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5055,7 +5135,7 @@ func (x *TriggerUpdateResponse) String() string { func (*TriggerUpdateResponse) ProtoMessage() {} func (x *TriggerUpdateResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[72] + mi := &file_daemon_proto_msgTypes[74] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5068,7 +5148,7 @@ func (x *TriggerUpdateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use TriggerUpdateResponse.ProtoReflect.Descriptor instead. func (*TriggerUpdateResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{72} + return file_daemon_proto_rawDescGZIP(), []int{74} } func (x *TriggerUpdateResponse) GetSuccess() bool { @@ -5096,7 +5176,7 @@ type GetPeerSSHHostKeyRequest struct { func (x *GetPeerSSHHostKeyRequest) Reset() { *x = GetPeerSSHHostKeyRequest{} - mi := &file_daemon_proto_msgTypes[73] + mi := &file_daemon_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5108,7 +5188,7 @@ func (x *GetPeerSSHHostKeyRequest) String() string { func (*GetPeerSSHHostKeyRequest) ProtoMessage() {} func (x *GetPeerSSHHostKeyRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[73] + mi := &file_daemon_proto_msgTypes[75] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5121,7 +5201,7 @@ func (x *GetPeerSSHHostKeyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetPeerSSHHostKeyRequest.ProtoReflect.Descriptor instead. func (*GetPeerSSHHostKeyRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{73} + return file_daemon_proto_rawDescGZIP(), []int{75} } func (x *GetPeerSSHHostKeyRequest) GetPeerAddress() string { @@ -5148,7 +5228,7 @@ type GetPeerSSHHostKeyResponse struct { func (x *GetPeerSSHHostKeyResponse) Reset() { *x = GetPeerSSHHostKeyResponse{} - mi := &file_daemon_proto_msgTypes[74] + mi := &file_daemon_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5160,7 +5240,7 @@ func (x *GetPeerSSHHostKeyResponse) String() string { func (*GetPeerSSHHostKeyResponse) ProtoMessage() {} func (x *GetPeerSSHHostKeyResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[74] + mi := &file_daemon_proto_msgTypes[76] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5173,7 +5253,7 @@ func (x *GetPeerSSHHostKeyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetPeerSSHHostKeyResponse.ProtoReflect.Descriptor instead. func (*GetPeerSSHHostKeyResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{74} + return file_daemon_proto_rawDescGZIP(), []int{76} } func (x *GetPeerSSHHostKeyResponse) GetSshHostKey() []byte { @@ -5215,7 +5295,7 @@ type RequestJWTAuthRequest struct { func (x *RequestJWTAuthRequest) Reset() { *x = RequestJWTAuthRequest{} - mi := &file_daemon_proto_msgTypes[75] + mi := &file_daemon_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5227,7 +5307,7 @@ func (x *RequestJWTAuthRequest) String() string { func (*RequestJWTAuthRequest) ProtoMessage() {} func (x *RequestJWTAuthRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[75] + mi := &file_daemon_proto_msgTypes[77] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5240,7 +5320,7 @@ func (x *RequestJWTAuthRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RequestJWTAuthRequest.ProtoReflect.Descriptor instead. func (*RequestJWTAuthRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{75} + return file_daemon_proto_rawDescGZIP(), []int{77} } func (x *RequestJWTAuthRequest) GetHint() string { @@ -5273,7 +5353,7 @@ type RequestJWTAuthResponse struct { func (x *RequestJWTAuthResponse) Reset() { *x = RequestJWTAuthResponse{} - mi := &file_daemon_proto_msgTypes[76] + mi := &file_daemon_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5285,7 +5365,7 @@ func (x *RequestJWTAuthResponse) String() string { func (*RequestJWTAuthResponse) ProtoMessage() {} func (x *RequestJWTAuthResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[76] + mi := &file_daemon_proto_msgTypes[78] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5298,7 +5378,7 @@ func (x *RequestJWTAuthResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RequestJWTAuthResponse.ProtoReflect.Descriptor instead. func (*RequestJWTAuthResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{76} + return file_daemon_proto_rawDescGZIP(), []int{78} } func (x *RequestJWTAuthResponse) GetVerificationURI() string { @@ -5363,7 +5443,7 @@ type WaitJWTTokenRequest struct { func (x *WaitJWTTokenRequest) Reset() { *x = WaitJWTTokenRequest{} - mi := &file_daemon_proto_msgTypes[77] + mi := &file_daemon_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5375,7 +5455,7 @@ func (x *WaitJWTTokenRequest) String() string { func (*WaitJWTTokenRequest) ProtoMessage() {} func (x *WaitJWTTokenRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[77] + mi := &file_daemon_proto_msgTypes[79] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5388,7 +5468,7 @@ func (x *WaitJWTTokenRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use WaitJWTTokenRequest.ProtoReflect.Descriptor instead. func (*WaitJWTTokenRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{77} + return file_daemon_proto_rawDescGZIP(), []int{79} } func (x *WaitJWTTokenRequest) GetDeviceCode() string { @@ -5420,7 +5500,7 @@ type WaitJWTTokenResponse struct { func (x *WaitJWTTokenResponse) Reset() { *x = WaitJWTTokenResponse{} - mi := &file_daemon_proto_msgTypes[78] + mi := &file_daemon_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5432,7 +5512,7 @@ func (x *WaitJWTTokenResponse) String() string { func (*WaitJWTTokenResponse) ProtoMessage() {} func (x *WaitJWTTokenResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[78] + mi := &file_daemon_proto_msgTypes[80] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5445,7 +5525,7 @@ func (x *WaitJWTTokenResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use WaitJWTTokenResponse.ProtoReflect.Descriptor instead. func (*WaitJWTTokenResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{78} + return file_daemon_proto_rawDescGZIP(), []int{80} } func (x *WaitJWTTokenResponse) GetToken() string { @@ -5481,7 +5561,7 @@ type RequestExtendAuthSessionRequest struct { func (x *RequestExtendAuthSessionRequest) Reset() { *x = RequestExtendAuthSessionRequest{} - mi := &file_daemon_proto_msgTypes[79] + mi := &file_daemon_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5493,7 +5573,7 @@ func (x *RequestExtendAuthSessionRequest) String() string { func (*RequestExtendAuthSessionRequest) ProtoMessage() {} func (x *RequestExtendAuthSessionRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[79] + mi := &file_daemon_proto_msgTypes[81] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5506,7 +5586,7 @@ func (x *RequestExtendAuthSessionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RequestExtendAuthSessionRequest.ProtoReflect.Descriptor instead. func (*RequestExtendAuthSessionRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{79} + return file_daemon_proto_rawDescGZIP(), []int{81} } func (x *RequestExtendAuthSessionRequest) GetHint() string { @@ -5537,7 +5617,7 @@ type RequestExtendAuthSessionResponse struct { func (x *RequestExtendAuthSessionResponse) Reset() { *x = RequestExtendAuthSessionResponse{} - mi := &file_daemon_proto_msgTypes[80] + mi := &file_daemon_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5549,7 +5629,7 @@ func (x *RequestExtendAuthSessionResponse) String() string { func (*RequestExtendAuthSessionResponse) ProtoMessage() {} func (x *RequestExtendAuthSessionResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[80] + mi := &file_daemon_proto_msgTypes[82] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5562,7 +5642,7 @@ func (x *RequestExtendAuthSessionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RequestExtendAuthSessionResponse.ProtoReflect.Descriptor instead. func (*RequestExtendAuthSessionResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{80} + return file_daemon_proto_rawDescGZIP(), []int{82} } func (x *RequestExtendAuthSessionResponse) GetVerificationURI() string { @@ -5615,7 +5695,7 @@ type WaitExtendAuthSessionRequest struct { func (x *WaitExtendAuthSessionRequest) Reset() { *x = WaitExtendAuthSessionRequest{} - mi := &file_daemon_proto_msgTypes[81] + mi := &file_daemon_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5627,7 +5707,7 @@ func (x *WaitExtendAuthSessionRequest) String() string { func (*WaitExtendAuthSessionRequest) ProtoMessage() {} func (x *WaitExtendAuthSessionRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[81] + mi := &file_daemon_proto_msgTypes[83] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5640,7 +5720,7 @@ func (x *WaitExtendAuthSessionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use WaitExtendAuthSessionRequest.ProtoReflect.Descriptor instead. func (*WaitExtendAuthSessionRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{81} + return file_daemon_proto_rawDescGZIP(), []int{83} } func (x *WaitExtendAuthSessionRequest) GetDeviceCode() string { @@ -5669,7 +5749,7 @@ type WaitExtendAuthSessionResponse struct { func (x *WaitExtendAuthSessionResponse) Reset() { *x = WaitExtendAuthSessionResponse{} - mi := &file_daemon_proto_msgTypes[82] + mi := &file_daemon_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5681,7 +5761,7 @@ func (x *WaitExtendAuthSessionResponse) String() string { func (*WaitExtendAuthSessionResponse) ProtoMessage() {} func (x *WaitExtendAuthSessionResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[82] + mi := &file_daemon_proto_msgTypes[84] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5694,7 +5774,7 @@ func (x *WaitExtendAuthSessionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use WaitExtendAuthSessionResponse.ProtoReflect.Descriptor instead. func (*WaitExtendAuthSessionResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{82} + return file_daemon_proto_rawDescGZIP(), []int{84} } func (x *WaitExtendAuthSessionResponse) GetSessionExpiresAt() *timestamppb.Timestamp { @@ -5714,7 +5794,7 @@ type DismissSessionWarningRequest struct { func (x *DismissSessionWarningRequest) Reset() { *x = DismissSessionWarningRequest{} - mi := &file_daemon_proto_msgTypes[83] + mi := &file_daemon_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5726,7 +5806,7 @@ func (x *DismissSessionWarningRequest) String() string { func (*DismissSessionWarningRequest) ProtoMessage() {} func (x *DismissSessionWarningRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[83] + mi := &file_daemon_proto_msgTypes[85] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5739,7 +5819,7 @@ func (x *DismissSessionWarningRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DismissSessionWarningRequest.ProtoReflect.Descriptor instead. func (*DismissSessionWarningRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{83} + return file_daemon_proto_rawDescGZIP(), []int{85} } // DismissSessionWarningResponse acknowledges the dismissal. Carries no @@ -5753,7 +5833,7 @@ type DismissSessionWarningResponse struct { func (x *DismissSessionWarningResponse) Reset() { *x = DismissSessionWarningResponse{} - mi := &file_daemon_proto_msgTypes[84] + mi := &file_daemon_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5765,7 +5845,7 @@ func (x *DismissSessionWarningResponse) String() string { func (*DismissSessionWarningResponse) ProtoMessage() {} func (x *DismissSessionWarningResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[84] + mi := &file_daemon_proto_msgTypes[86] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5778,7 +5858,7 @@ func (x *DismissSessionWarningResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DismissSessionWarningResponse.ProtoReflect.Descriptor instead. func (*DismissSessionWarningResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{84} + return file_daemon_proto_rawDescGZIP(), []int{86} } // StartCPUProfileRequest for starting CPU profiling @@ -5790,7 +5870,7 @@ type StartCPUProfileRequest struct { func (x *StartCPUProfileRequest) Reset() { *x = StartCPUProfileRequest{} - mi := &file_daemon_proto_msgTypes[85] + mi := &file_daemon_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5802,7 +5882,7 @@ func (x *StartCPUProfileRequest) String() string { func (*StartCPUProfileRequest) ProtoMessage() {} func (x *StartCPUProfileRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[85] + mi := &file_daemon_proto_msgTypes[87] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5815,7 +5895,7 @@ func (x *StartCPUProfileRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StartCPUProfileRequest.ProtoReflect.Descriptor instead. func (*StartCPUProfileRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{85} + return file_daemon_proto_rawDescGZIP(), []int{87} } // StartCPUProfileResponse confirms CPU profiling has started @@ -5827,7 +5907,7 @@ type StartCPUProfileResponse struct { func (x *StartCPUProfileResponse) Reset() { *x = StartCPUProfileResponse{} - mi := &file_daemon_proto_msgTypes[86] + mi := &file_daemon_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5839,7 +5919,7 @@ func (x *StartCPUProfileResponse) String() string { func (*StartCPUProfileResponse) ProtoMessage() {} func (x *StartCPUProfileResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[86] + mi := &file_daemon_proto_msgTypes[88] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5852,7 +5932,7 @@ func (x *StartCPUProfileResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StartCPUProfileResponse.ProtoReflect.Descriptor instead. func (*StartCPUProfileResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{86} + return file_daemon_proto_rawDescGZIP(), []int{88} } // StopCPUProfileRequest for stopping CPU profiling @@ -5864,7 +5944,7 @@ type StopCPUProfileRequest struct { func (x *StopCPUProfileRequest) Reset() { *x = StopCPUProfileRequest{} - mi := &file_daemon_proto_msgTypes[87] + mi := &file_daemon_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5876,7 +5956,7 @@ func (x *StopCPUProfileRequest) String() string { func (*StopCPUProfileRequest) ProtoMessage() {} func (x *StopCPUProfileRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[87] + mi := &file_daemon_proto_msgTypes[89] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5889,7 +5969,7 @@ func (x *StopCPUProfileRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StopCPUProfileRequest.ProtoReflect.Descriptor instead. func (*StopCPUProfileRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{87} + return file_daemon_proto_rawDescGZIP(), []int{89} } // StopCPUProfileResponse confirms CPU profiling has stopped @@ -5901,7 +5981,7 @@ type StopCPUProfileResponse struct { func (x *StopCPUProfileResponse) Reset() { *x = StopCPUProfileResponse{} - mi := &file_daemon_proto_msgTypes[88] + mi := &file_daemon_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5913,7 +5993,7 @@ func (x *StopCPUProfileResponse) String() string { func (*StopCPUProfileResponse) ProtoMessage() {} func (x *StopCPUProfileResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[88] + mi := &file_daemon_proto_msgTypes[90] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5926,7 +6006,7 @@ func (x *StopCPUProfileResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StopCPUProfileResponse.ProtoReflect.Descriptor instead. func (*StopCPUProfileResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{88} + return file_daemon_proto_rawDescGZIP(), []int{90} } type InstallerResultRequest struct { @@ -5937,7 +6017,7 @@ type InstallerResultRequest struct { func (x *InstallerResultRequest) Reset() { *x = InstallerResultRequest{} - mi := &file_daemon_proto_msgTypes[89] + mi := &file_daemon_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5949,7 +6029,7 @@ func (x *InstallerResultRequest) String() string { func (*InstallerResultRequest) ProtoMessage() {} func (x *InstallerResultRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[89] + mi := &file_daemon_proto_msgTypes[91] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5962,7 +6042,7 @@ func (x *InstallerResultRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use InstallerResultRequest.ProtoReflect.Descriptor instead. func (*InstallerResultRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{89} + return file_daemon_proto_rawDescGZIP(), []int{91} } type InstallerResultResponse struct { @@ -5975,7 +6055,7 @@ type InstallerResultResponse struct { func (x *InstallerResultResponse) Reset() { *x = InstallerResultResponse{} - mi := &file_daemon_proto_msgTypes[90] + mi := &file_daemon_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5987,7 +6067,7 @@ func (x *InstallerResultResponse) String() string { func (*InstallerResultResponse) ProtoMessage() {} func (x *InstallerResultResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[90] + mi := &file_daemon_proto_msgTypes[92] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6000,7 +6080,7 @@ func (x *InstallerResultResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use InstallerResultResponse.ProtoReflect.Descriptor instead. func (*InstallerResultResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{90} + return file_daemon_proto_rawDescGZIP(), []int{92} } func (x *InstallerResultResponse) GetSuccess() bool { @@ -6033,7 +6113,7 @@ type ExposeServiceRequest struct { func (x *ExposeServiceRequest) Reset() { *x = ExposeServiceRequest{} - mi := &file_daemon_proto_msgTypes[91] + mi := &file_daemon_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6045,7 +6125,7 @@ func (x *ExposeServiceRequest) String() string { func (*ExposeServiceRequest) ProtoMessage() {} func (x *ExposeServiceRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[91] + mi := &file_daemon_proto_msgTypes[93] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6058,7 +6138,7 @@ func (x *ExposeServiceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ExposeServiceRequest.ProtoReflect.Descriptor instead. func (*ExposeServiceRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{91} + return file_daemon_proto_rawDescGZIP(), []int{93} } func (x *ExposeServiceRequest) GetPort() uint32 { @@ -6129,7 +6209,7 @@ type ExposeServiceEvent struct { func (x *ExposeServiceEvent) Reset() { *x = ExposeServiceEvent{} - mi := &file_daemon_proto_msgTypes[92] + mi := &file_daemon_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6141,7 +6221,7 @@ func (x *ExposeServiceEvent) String() string { func (*ExposeServiceEvent) ProtoMessage() {} func (x *ExposeServiceEvent) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[92] + mi := &file_daemon_proto_msgTypes[94] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6154,7 +6234,7 @@ func (x *ExposeServiceEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use ExposeServiceEvent.ProtoReflect.Descriptor instead. func (*ExposeServiceEvent) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{92} + return file_daemon_proto_rawDescGZIP(), []int{94} } func (x *ExposeServiceEvent) GetEvent() isExposeServiceEvent_Event { @@ -6195,7 +6275,7 @@ type ExposeServiceReady struct { func (x *ExposeServiceReady) Reset() { *x = ExposeServiceReady{} - mi := &file_daemon_proto_msgTypes[93] + mi := &file_daemon_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6207,7 +6287,7 @@ func (x *ExposeServiceReady) String() string { func (*ExposeServiceReady) ProtoMessage() {} func (x *ExposeServiceReady) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[93] + mi := &file_daemon_proto_msgTypes[95] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6220,7 +6300,7 @@ func (x *ExposeServiceReady) ProtoReflect() protoreflect.Message { // Deprecated: Use ExposeServiceReady.ProtoReflect.Descriptor instead. func (*ExposeServiceReady) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{93} + return file_daemon_proto_rawDescGZIP(), []int{95} } func (x *ExposeServiceReady) GetServiceName() string { @@ -6265,7 +6345,7 @@ type StartCaptureRequest struct { func (x *StartCaptureRequest) Reset() { *x = StartCaptureRequest{} - mi := &file_daemon_proto_msgTypes[94] + mi := &file_daemon_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6277,7 +6357,7 @@ func (x *StartCaptureRequest) String() string { func (*StartCaptureRequest) ProtoMessage() {} func (x *StartCaptureRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[94] + mi := &file_daemon_proto_msgTypes[96] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6290,7 +6370,7 @@ func (x *StartCaptureRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StartCaptureRequest.ProtoReflect.Descriptor instead. func (*StartCaptureRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{94} + return file_daemon_proto_rawDescGZIP(), []int{96} } func (x *StartCaptureRequest) GetTextOutput() bool { @@ -6344,7 +6424,7 @@ type CapturePacket struct { func (x *CapturePacket) Reset() { *x = CapturePacket{} - mi := &file_daemon_proto_msgTypes[95] + mi := &file_daemon_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6356,7 +6436,7 @@ func (x *CapturePacket) String() string { func (*CapturePacket) ProtoMessage() {} func (x *CapturePacket) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[95] + mi := &file_daemon_proto_msgTypes[97] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6369,7 +6449,7 @@ func (x *CapturePacket) ProtoReflect() protoreflect.Message { // Deprecated: Use CapturePacket.ProtoReflect.Descriptor instead. func (*CapturePacket) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{95} + return file_daemon_proto_rawDescGZIP(), []int{97} } func (x *CapturePacket) GetData() []byte { @@ -6390,7 +6470,7 @@ type StartBundleCaptureRequest struct { func (x *StartBundleCaptureRequest) Reset() { *x = StartBundleCaptureRequest{} - mi := &file_daemon_proto_msgTypes[96] + mi := &file_daemon_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6402,7 +6482,7 @@ func (x *StartBundleCaptureRequest) String() string { func (*StartBundleCaptureRequest) ProtoMessage() {} func (x *StartBundleCaptureRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[96] + mi := &file_daemon_proto_msgTypes[98] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6415,7 +6495,7 @@ func (x *StartBundleCaptureRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StartBundleCaptureRequest.ProtoReflect.Descriptor instead. func (*StartBundleCaptureRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{96} + return file_daemon_proto_rawDescGZIP(), []int{98} } func (x *StartBundleCaptureRequest) GetTimeout() *durationpb.Duration { @@ -6433,7 +6513,7 @@ type StartBundleCaptureResponse struct { func (x *StartBundleCaptureResponse) Reset() { *x = StartBundleCaptureResponse{} - mi := &file_daemon_proto_msgTypes[97] + mi := &file_daemon_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6445,7 +6525,7 @@ func (x *StartBundleCaptureResponse) String() string { func (*StartBundleCaptureResponse) ProtoMessage() {} func (x *StartBundleCaptureResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[97] + mi := &file_daemon_proto_msgTypes[99] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6458,7 +6538,7 @@ func (x *StartBundleCaptureResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StartBundleCaptureResponse.ProtoReflect.Descriptor instead. func (*StartBundleCaptureResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{97} + return file_daemon_proto_rawDescGZIP(), []int{99} } type StopBundleCaptureRequest struct { @@ -6469,7 +6549,7 @@ type StopBundleCaptureRequest struct { func (x *StopBundleCaptureRequest) Reset() { *x = StopBundleCaptureRequest{} - mi := &file_daemon_proto_msgTypes[98] + mi := &file_daemon_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6481,7 +6561,7 @@ func (x *StopBundleCaptureRequest) String() string { func (*StopBundleCaptureRequest) ProtoMessage() {} func (x *StopBundleCaptureRequest) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[98] + mi := &file_daemon_proto_msgTypes[100] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6494,7 +6574,7 @@ func (x *StopBundleCaptureRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StopBundleCaptureRequest.ProtoReflect.Descriptor instead. func (*StopBundleCaptureRequest) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{98} + return file_daemon_proto_rawDescGZIP(), []int{100} } type StopBundleCaptureResponse struct { @@ -6505,7 +6585,7 @@ type StopBundleCaptureResponse struct { func (x *StopBundleCaptureResponse) Reset() { *x = StopBundleCaptureResponse{} - mi := &file_daemon_proto_msgTypes[99] + mi := &file_daemon_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6517,7 +6597,7 @@ func (x *StopBundleCaptureResponse) String() string { func (*StopBundleCaptureResponse) ProtoMessage() {} func (x *StopBundleCaptureResponse) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[99] + mi := &file_daemon_proto_msgTypes[101] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6530,7 +6610,7 @@ func (x *StopBundleCaptureResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StopBundleCaptureResponse.ProtoReflect.Descriptor instead. func (*StopBundleCaptureResponse) Descriptor() ([]byte, []int) { - return file_daemon_proto_rawDescGZIP(), []int{99} + return file_daemon_proto_rawDescGZIP(), []int{101} } type PortInfo_Range struct { @@ -6543,7 +6623,7 @@ type PortInfo_Range struct { func (x *PortInfo_Range) Reset() { *x = PortInfo_Range{} - mi := &file_daemon_proto_msgTypes[101] + mi := &file_daemon_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6555,7 +6635,7 @@ func (x *PortInfo_Range) String() string { func (*PortInfo_Range) ProtoMessage() {} func (x *PortInfo_Range) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[101] + mi := &file_daemon_proto_msgTypes[103] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6863,7 +6943,10 @@ const file_daemon_proto_rawDesc = "" + "\x05level\x18\x01 \x01(\x0e2\x10.daemon.LogLevelR\x05level\"<\n" + "\x12SetLogLevelRequest\x12&\n" + "\x05level\x18\x01 \x01(\x0e2\x10.daemon.LogLevelR\x05level\"\x15\n" + - "\x13SetLogLevelResponse\"\x1b\n" + + "\x13SetLogLevelResponse\"*\n" + + "\x14RegisterUILogRequest\x12\x12\n" + + "\x04path\x18\x01 \x01(\tR\x04path\"\x17\n" + + "\x15RegisterUILogResponse\"\x1b\n" + "\x05State\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\"\x13\n" + "\x11ListStatesRequest\";\n" + @@ -7164,7 +7247,7 @@ const file_daemon_proto_rawDesc = "" + "\n" + "EXPOSE_UDP\x10\x03\x12\x0e\n" + "\n" + - "EXPOSE_TLS\x10\x042\xb6\x1a\n" + + "EXPOSE_TLS\x10\x042\x86\x1b\n" + "\rDaemonService\x126\n" + "\x05Login\x12\x14.daemon.LoginRequest\x1a\x15.daemon.LoginResponse\"\x00\x12K\n" + "\fWaitSSOLogin\x12\x1b.daemon.WaitSSOLoginRequest\x1a\x1c.daemon.WaitSSOLoginResponse\"\x00\x12-\n" + @@ -7192,6 +7275,7 @@ const file_daemon_proto_rawDesc = "" + "\x11StopBundleCapture\x12 .daemon.StopBundleCaptureRequest\x1a!.daemon.StopBundleCaptureResponse\"\x00\x12D\n" + "\x0fSubscribeEvents\x12\x18.daemon.SubscribeRequest\x1a\x13.daemon.SystemEvent\"\x000\x01\x12B\n" + "\tGetEvents\x12\x18.daemon.GetEventsRequest\x1a\x19.daemon.GetEventsResponse\"\x00\x12N\n" + + "\rRegisterUILog\x12\x1c.daemon.RegisterUILogRequest\x1a\x1d.daemon.RegisterUILogResponse\"\x00\x12N\n" + "\rSwitchProfile\x12\x1c.daemon.SwitchProfileRequest\x1a\x1d.daemon.SwitchProfileResponse\"\x00\x12B\n" + "\tSetConfig\x12\x18.daemon.SetConfigRequest\x1a\x19.daemon.SetConfigResponse\"\x00\x12E\n" + "\n" + @@ -7226,7 +7310,7 @@ func file_daemon_proto_rawDescGZIP() []byte { } var file_daemon_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_daemon_proto_msgTypes = make([]protoimpl.MessageInfo, 103) +var file_daemon_proto_msgTypes = make([]protoimpl.MessageInfo, 105) var file_daemon_proto_goTypes = []any{ (LogLevel)(0), // 0: daemon.LogLevel (ExposeProtocol)(0), // 1: daemon.ExposeProtocol @@ -7269,82 +7353,84 @@ var file_daemon_proto_goTypes = []any{ (*GetLogLevelResponse)(nil), // 38: daemon.GetLogLevelResponse (*SetLogLevelRequest)(nil), // 39: daemon.SetLogLevelRequest (*SetLogLevelResponse)(nil), // 40: daemon.SetLogLevelResponse - (*State)(nil), // 41: daemon.State - (*ListStatesRequest)(nil), // 42: daemon.ListStatesRequest - (*ListStatesResponse)(nil), // 43: daemon.ListStatesResponse - (*CleanStateRequest)(nil), // 44: daemon.CleanStateRequest - (*CleanStateResponse)(nil), // 45: daemon.CleanStateResponse - (*DeleteStateRequest)(nil), // 46: daemon.DeleteStateRequest - (*DeleteStateResponse)(nil), // 47: daemon.DeleteStateResponse - (*SetSyncResponsePersistenceRequest)(nil), // 48: daemon.SetSyncResponsePersistenceRequest - (*SetSyncResponsePersistenceResponse)(nil), // 49: daemon.SetSyncResponsePersistenceResponse - (*TCPFlags)(nil), // 50: daemon.TCPFlags - (*TracePacketRequest)(nil), // 51: daemon.TracePacketRequest - (*TraceStage)(nil), // 52: daemon.TraceStage - (*TracePacketResponse)(nil), // 53: daemon.TracePacketResponse - (*SubscribeRequest)(nil), // 54: daemon.SubscribeRequest - (*SystemEvent)(nil), // 55: daemon.SystemEvent - (*GetEventsRequest)(nil), // 56: daemon.GetEventsRequest - (*GetEventsResponse)(nil), // 57: daemon.GetEventsResponse - (*SwitchProfileRequest)(nil), // 58: daemon.SwitchProfileRequest - (*SwitchProfileResponse)(nil), // 59: daemon.SwitchProfileResponse - (*SetConfigRequest)(nil), // 60: daemon.SetConfigRequest - (*SetConfigResponse)(nil), // 61: daemon.SetConfigResponse - (*AddProfileRequest)(nil), // 62: daemon.AddProfileRequest - (*AddProfileResponse)(nil), // 63: daemon.AddProfileResponse - (*RemoveProfileRequest)(nil), // 64: daemon.RemoveProfileRequest - (*RemoveProfileResponse)(nil), // 65: daemon.RemoveProfileResponse - (*ListProfilesRequest)(nil), // 66: daemon.ListProfilesRequest - (*ListProfilesResponse)(nil), // 67: daemon.ListProfilesResponse - (*Profile)(nil), // 68: daemon.Profile - (*GetActiveProfileRequest)(nil), // 69: daemon.GetActiveProfileRequest - (*GetActiveProfileResponse)(nil), // 70: daemon.GetActiveProfileResponse - (*LogoutRequest)(nil), // 71: daemon.LogoutRequest - (*LogoutResponse)(nil), // 72: daemon.LogoutResponse - (*GetFeaturesRequest)(nil), // 73: daemon.GetFeaturesRequest - (*GetFeaturesResponse)(nil), // 74: daemon.GetFeaturesResponse - (*TriggerUpdateRequest)(nil), // 75: daemon.TriggerUpdateRequest - (*TriggerUpdateResponse)(nil), // 76: daemon.TriggerUpdateResponse - (*GetPeerSSHHostKeyRequest)(nil), // 77: daemon.GetPeerSSHHostKeyRequest - (*GetPeerSSHHostKeyResponse)(nil), // 78: daemon.GetPeerSSHHostKeyResponse - (*RequestJWTAuthRequest)(nil), // 79: daemon.RequestJWTAuthRequest - (*RequestJWTAuthResponse)(nil), // 80: daemon.RequestJWTAuthResponse - (*WaitJWTTokenRequest)(nil), // 81: daemon.WaitJWTTokenRequest - (*WaitJWTTokenResponse)(nil), // 82: daemon.WaitJWTTokenResponse - (*RequestExtendAuthSessionRequest)(nil), // 83: daemon.RequestExtendAuthSessionRequest - (*RequestExtendAuthSessionResponse)(nil), // 84: daemon.RequestExtendAuthSessionResponse - (*WaitExtendAuthSessionRequest)(nil), // 85: daemon.WaitExtendAuthSessionRequest - (*WaitExtendAuthSessionResponse)(nil), // 86: daemon.WaitExtendAuthSessionResponse - (*DismissSessionWarningRequest)(nil), // 87: daemon.DismissSessionWarningRequest - (*DismissSessionWarningResponse)(nil), // 88: daemon.DismissSessionWarningResponse - (*StartCPUProfileRequest)(nil), // 89: daemon.StartCPUProfileRequest - (*StartCPUProfileResponse)(nil), // 90: daemon.StartCPUProfileResponse - (*StopCPUProfileRequest)(nil), // 91: daemon.StopCPUProfileRequest - (*StopCPUProfileResponse)(nil), // 92: daemon.StopCPUProfileResponse - (*InstallerResultRequest)(nil), // 93: daemon.InstallerResultRequest - (*InstallerResultResponse)(nil), // 94: daemon.InstallerResultResponse - (*ExposeServiceRequest)(nil), // 95: daemon.ExposeServiceRequest - (*ExposeServiceEvent)(nil), // 96: daemon.ExposeServiceEvent - (*ExposeServiceReady)(nil), // 97: daemon.ExposeServiceReady - (*StartCaptureRequest)(nil), // 98: daemon.StartCaptureRequest - (*CapturePacket)(nil), // 99: daemon.CapturePacket - (*StartBundleCaptureRequest)(nil), // 100: daemon.StartBundleCaptureRequest - (*StartBundleCaptureResponse)(nil), // 101: daemon.StartBundleCaptureResponse - (*StopBundleCaptureRequest)(nil), // 102: daemon.StopBundleCaptureRequest - (*StopBundleCaptureResponse)(nil), // 103: daemon.StopBundleCaptureResponse - nil, // 104: daemon.Network.ResolvedIPsEntry - (*PortInfo_Range)(nil), // 105: daemon.PortInfo.Range - nil, // 106: daemon.SystemEvent.MetadataEntry - (*durationpb.Duration)(nil), // 107: google.protobuf.Duration - (*timestamppb.Timestamp)(nil), // 108: google.protobuf.Timestamp + (*RegisterUILogRequest)(nil), // 41: daemon.RegisterUILogRequest + (*RegisterUILogResponse)(nil), // 42: daemon.RegisterUILogResponse + (*State)(nil), // 43: daemon.State + (*ListStatesRequest)(nil), // 44: daemon.ListStatesRequest + (*ListStatesResponse)(nil), // 45: daemon.ListStatesResponse + (*CleanStateRequest)(nil), // 46: daemon.CleanStateRequest + (*CleanStateResponse)(nil), // 47: daemon.CleanStateResponse + (*DeleteStateRequest)(nil), // 48: daemon.DeleteStateRequest + (*DeleteStateResponse)(nil), // 49: daemon.DeleteStateResponse + (*SetSyncResponsePersistenceRequest)(nil), // 50: daemon.SetSyncResponsePersistenceRequest + (*SetSyncResponsePersistenceResponse)(nil), // 51: daemon.SetSyncResponsePersistenceResponse + (*TCPFlags)(nil), // 52: daemon.TCPFlags + (*TracePacketRequest)(nil), // 53: daemon.TracePacketRequest + (*TraceStage)(nil), // 54: daemon.TraceStage + (*TracePacketResponse)(nil), // 55: daemon.TracePacketResponse + (*SubscribeRequest)(nil), // 56: daemon.SubscribeRequest + (*SystemEvent)(nil), // 57: daemon.SystemEvent + (*GetEventsRequest)(nil), // 58: daemon.GetEventsRequest + (*GetEventsResponse)(nil), // 59: daemon.GetEventsResponse + (*SwitchProfileRequest)(nil), // 60: daemon.SwitchProfileRequest + (*SwitchProfileResponse)(nil), // 61: daemon.SwitchProfileResponse + (*SetConfigRequest)(nil), // 62: daemon.SetConfigRequest + (*SetConfigResponse)(nil), // 63: daemon.SetConfigResponse + (*AddProfileRequest)(nil), // 64: daemon.AddProfileRequest + (*AddProfileResponse)(nil), // 65: daemon.AddProfileResponse + (*RemoveProfileRequest)(nil), // 66: daemon.RemoveProfileRequest + (*RemoveProfileResponse)(nil), // 67: daemon.RemoveProfileResponse + (*ListProfilesRequest)(nil), // 68: daemon.ListProfilesRequest + (*ListProfilesResponse)(nil), // 69: daemon.ListProfilesResponse + (*Profile)(nil), // 70: daemon.Profile + (*GetActiveProfileRequest)(nil), // 71: daemon.GetActiveProfileRequest + (*GetActiveProfileResponse)(nil), // 72: daemon.GetActiveProfileResponse + (*LogoutRequest)(nil), // 73: daemon.LogoutRequest + (*LogoutResponse)(nil), // 74: daemon.LogoutResponse + (*GetFeaturesRequest)(nil), // 75: daemon.GetFeaturesRequest + (*GetFeaturesResponse)(nil), // 76: daemon.GetFeaturesResponse + (*TriggerUpdateRequest)(nil), // 77: daemon.TriggerUpdateRequest + (*TriggerUpdateResponse)(nil), // 78: daemon.TriggerUpdateResponse + (*GetPeerSSHHostKeyRequest)(nil), // 79: daemon.GetPeerSSHHostKeyRequest + (*GetPeerSSHHostKeyResponse)(nil), // 80: daemon.GetPeerSSHHostKeyResponse + (*RequestJWTAuthRequest)(nil), // 81: daemon.RequestJWTAuthRequest + (*RequestJWTAuthResponse)(nil), // 82: daemon.RequestJWTAuthResponse + (*WaitJWTTokenRequest)(nil), // 83: daemon.WaitJWTTokenRequest + (*WaitJWTTokenResponse)(nil), // 84: daemon.WaitJWTTokenResponse + (*RequestExtendAuthSessionRequest)(nil), // 85: daemon.RequestExtendAuthSessionRequest + (*RequestExtendAuthSessionResponse)(nil), // 86: daemon.RequestExtendAuthSessionResponse + (*WaitExtendAuthSessionRequest)(nil), // 87: daemon.WaitExtendAuthSessionRequest + (*WaitExtendAuthSessionResponse)(nil), // 88: daemon.WaitExtendAuthSessionResponse + (*DismissSessionWarningRequest)(nil), // 89: daemon.DismissSessionWarningRequest + (*DismissSessionWarningResponse)(nil), // 90: daemon.DismissSessionWarningResponse + (*StartCPUProfileRequest)(nil), // 91: daemon.StartCPUProfileRequest + (*StartCPUProfileResponse)(nil), // 92: daemon.StartCPUProfileResponse + (*StopCPUProfileRequest)(nil), // 93: daemon.StopCPUProfileRequest + (*StopCPUProfileResponse)(nil), // 94: daemon.StopCPUProfileResponse + (*InstallerResultRequest)(nil), // 95: daemon.InstallerResultRequest + (*InstallerResultResponse)(nil), // 96: daemon.InstallerResultResponse + (*ExposeServiceRequest)(nil), // 97: daemon.ExposeServiceRequest + (*ExposeServiceEvent)(nil), // 98: daemon.ExposeServiceEvent + (*ExposeServiceReady)(nil), // 99: daemon.ExposeServiceReady + (*StartCaptureRequest)(nil), // 100: daemon.StartCaptureRequest + (*CapturePacket)(nil), // 101: daemon.CapturePacket + (*StartBundleCaptureRequest)(nil), // 102: daemon.StartBundleCaptureRequest + (*StartBundleCaptureResponse)(nil), // 103: daemon.StartBundleCaptureResponse + (*StopBundleCaptureRequest)(nil), // 104: daemon.StopBundleCaptureRequest + (*StopBundleCaptureResponse)(nil), // 105: daemon.StopBundleCaptureResponse + nil, // 106: daemon.Network.ResolvedIPsEntry + (*PortInfo_Range)(nil), // 107: daemon.PortInfo.Range + nil, // 108: daemon.SystemEvent.MetadataEntry + (*durationpb.Duration)(nil), // 109: google.protobuf.Duration + (*timestamppb.Timestamp)(nil), // 110: google.protobuf.Timestamp } var file_daemon_proto_depIdxs = []int32{ - 107, // 0: daemon.LoginRequest.dnsRouteInterval:type_name -> google.protobuf.Duration + 109, // 0: daemon.LoginRequest.dnsRouteInterval:type_name -> google.protobuf.Duration 25, // 1: daemon.StatusResponse.fullStatus:type_name -> daemon.FullStatus - 108, // 2: daemon.StatusResponse.sessionExpiresAt:type_name -> google.protobuf.Timestamp - 108, // 3: daemon.PeerState.connStatusUpdate:type_name -> google.protobuf.Timestamp - 108, // 4: daemon.PeerState.lastWireguardHandshake:type_name -> google.protobuf.Timestamp - 107, // 5: daemon.PeerState.latency:type_name -> google.protobuf.Duration + 110, // 2: daemon.StatusResponse.sessionExpiresAt:type_name -> google.protobuf.Timestamp + 110, // 3: daemon.PeerState.connStatusUpdate:type_name -> google.protobuf.Timestamp + 110, // 4: daemon.PeerState.lastWireguardHandshake:type_name -> google.protobuf.Timestamp + 109, // 5: daemon.PeerState.latency:type_name -> google.protobuf.Duration 23, // 6: daemon.SSHServerState.sessions:type_name -> daemon.SSHSessionInfo 20, // 7: daemon.FullStatus.managementState:type_name -> daemon.ManagementState 19, // 8: daemon.FullStatus.signalState:type_name -> daemon.SignalState @@ -7352,31 +7438,31 @@ var file_daemon_proto_depIdxs = []int32{ 17, // 10: daemon.FullStatus.peers:type_name -> daemon.PeerState 21, // 11: daemon.FullStatus.relays:type_name -> daemon.RelayState 22, // 12: daemon.FullStatus.dns_servers:type_name -> daemon.NSGroupState - 55, // 13: daemon.FullStatus.events:type_name -> daemon.SystemEvent + 57, // 13: daemon.FullStatus.events:type_name -> daemon.SystemEvent 24, // 14: daemon.FullStatus.sshServerState:type_name -> daemon.SSHServerState 31, // 15: daemon.ListNetworksResponse.routes:type_name -> daemon.Network - 104, // 16: daemon.Network.resolvedIPs:type_name -> daemon.Network.ResolvedIPsEntry - 105, // 17: daemon.PortInfo.range:type_name -> daemon.PortInfo.Range + 106, // 16: daemon.Network.resolvedIPs:type_name -> daemon.Network.ResolvedIPsEntry + 107, // 17: daemon.PortInfo.range:type_name -> daemon.PortInfo.Range 32, // 18: daemon.ForwardingRule.destinationPort:type_name -> daemon.PortInfo 32, // 19: daemon.ForwardingRule.translatedPort:type_name -> daemon.PortInfo 33, // 20: daemon.ForwardingRulesResponse.rules:type_name -> daemon.ForwardingRule 0, // 21: daemon.GetLogLevelResponse.level:type_name -> daemon.LogLevel 0, // 22: daemon.SetLogLevelRequest.level:type_name -> daemon.LogLevel - 41, // 23: daemon.ListStatesResponse.states:type_name -> daemon.State - 50, // 24: daemon.TracePacketRequest.tcp_flags:type_name -> daemon.TCPFlags - 52, // 25: daemon.TracePacketResponse.stages:type_name -> daemon.TraceStage + 43, // 23: daemon.ListStatesResponse.states:type_name -> daemon.State + 52, // 24: daemon.TracePacketRequest.tcp_flags:type_name -> daemon.TCPFlags + 54, // 25: daemon.TracePacketResponse.stages:type_name -> daemon.TraceStage 2, // 26: daemon.SystemEvent.severity:type_name -> daemon.SystemEvent.Severity 3, // 27: daemon.SystemEvent.category:type_name -> daemon.SystemEvent.Category - 108, // 28: daemon.SystemEvent.timestamp:type_name -> google.protobuf.Timestamp - 106, // 29: daemon.SystemEvent.metadata:type_name -> daemon.SystemEvent.MetadataEntry - 55, // 30: daemon.GetEventsResponse.events:type_name -> daemon.SystemEvent - 107, // 31: daemon.SetConfigRequest.dnsRouteInterval:type_name -> google.protobuf.Duration - 68, // 32: daemon.ListProfilesResponse.profiles:type_name -> daemon.Profile - 108, // 33: daemon.WaitExtendAuthSessionResponse.sessionExpiresAt:type_name -> google.protobuf.Timestamp + 110, // 28: daemon.SystemEvent.timestamp:type_name -> google.protobuf.Timestamp + 108, // 29: daemon.SystemEvent.metadata:type_name -> daemon.SystemEvent.MetadataEntry + 57, // 30: daemon.GetEventsResponse.events:type_name -> daemon.SystemEvent + 109, // 31: daemon.SetConfigRequest.dnsRouteInterval:type_name -> google.protobuf.Duration + 70, // 32: daemon.ListProfilesResponse.profiles:type_name -> daemon.Profile + 110, // 33: daemon.WaitExtendAuthSessionResponse.sessionExpiresAt:type_name -> google.protobuf.Timestamp 1, // 34: daemon.ExposeServiceRequest.protocol:type_name -> daemon.ExposeProtocol - 97, // 35: daemon.ExposeServiceEvent.ready:type_name -> daemon.ExposeServiceReady - 107, // 36: daemon.StartCaptureRequest.duration:type_name -> google.protobuf.Duration - 107, // 37: daemon.StartBundleCaptureRequest.timeout:type_name -> google.protobuf.Duration + 99, // 35: daemon.ExposeServiceEvent.ready:type_name -> daemon.ExposeServiceReady + 109, // 36: daemon.StartCaptureRequest.duration:type_name -> google.protobuf.Duration + 109, // 37: daemon.StartBundleCaptureRequest.timeout:type_name -> google.protobuf.Duration 30, // 38: daemon.Network.ResolvedIPsEntry.value:type_name -> daemon.IPList 5, // 39: daemon.DaemonService.Login:input_type -> daemon.LoginRequest 7, // 40: daemon.DaemonService.WaitSSOLogin:input_type -> daemon.WaitSSOLoginRequest @@ -7392,80 +7478,82 @@ var file_daemon_proto_depIdxs = []int32{ 35, // 50: daemon.DaemonService.DebugBundle:input_type -> daemon.DebugBundleRequest 37, // 51: daemon.DaemonService.GetLogLevel:input_type -> daemon.GetLogLevelRequest 39, // 52: daemon.DaemonService.SetLogLevel:input_type -> daemon.SetLogLevelRequest - 42, // 53: daemon.DaemonService.ListStates:input_type -> daemon.ListStatesRequest - 44, // 54: daemon.DaemonService.CleanState:input_type -> daemon.CleanStateRequest - 46, // 55: daemon.DaemonService.DeleteState:input_type -> daemon.DeleteStateRequest - 48, // 56: daemon.DaemonService.SetSyncResponsePersistence:input_type -> daemon.SetSyncResponsePersistenceRequest - 51, // 57: daemon.DaemonService.TracePacket:input_type -> daemon.TracePacketRequest - 98, // 58: daemon.DaemonService.StartCapture:input_type -> daemon.StartCaptureRequest - 100, // 59: daemon.DaemonService.StartBundleCapture:input_type -> daemon.StartBundleCaptureRequest - 102, // 60: daemon.DaemonService.StopBundleCapture:input_type -> daemon.StopBundleCaptureRequest - 54, // 61: daemon.DaemonService.SubscribeEvents:input_type -> daemon.SubscribeRequest - 56, // 62: daemon.DaemonService.GetEvents:input_type -> daemon.GetEventsRequest - 58, // 63: daemon.DaemonService.SwitchProfile:input_type -> daemon.SwitchProfileRequest - 60, // 64: daemon.DaemonService.SetConfig:input_type -> daemon.SetConfigRequest - 62, // 65: daemon.DaemonService.AddProfile:input_type -> daemon.AddProfileRequest - 64, // 66: daemon.DaemonService.RemoveProfile:input_type -> daemon.RemoveProfileRequest - 66, // 67: daemon.DaemonService.ListProfiles:input_type -> daemon.ListProfilesRequest - 69, // 68: daemon.DaemonService.GetActiveProfile:input_type -> daemon.GetActiveProfileRequest - 71, // 69: daemon.DaemonService.Logout:input_type -> daemon.LogoutRequest - 73, // 70: daemon.DaemonService.GetFeatures:input_type -> daemon.GetFeaturesRequest - 75, // 71: daemon.DaemonService.TriggerUpdate:input_type -> daemon.TriggerUpdateRequest - 77, // 72: daemon.DaemonService.GetPeerSSHHostKey:input_type -> daemon.GetPeerSSHHostKeyRequest - 79, // 73: daemon.DaemonService.RequestJWTAuth:input_type -> daemon.RequestJWTAuthRequest - 81, // 74: daemon.DaemonService.WaitJWTToken:input_type -> daemon.WaitJWTTokenRequest - 83, // 75: daemon.DaemonService.RequestExtendAuthSession:input_type -> daemon.RequestExtendAuthSessionRequest - 85, // 76: daemon.DaemonService.WaitExtendAuthSession:input_type -> daemon.WaitExtendAuthSessionRequest - 87, // 77: daemon.DaemonService.DismissSessionWarning:input_type -> daemon.DismissSessionWarningRequest - 89, // 78: daemon.DaemonService.StartCPUProfile:input_type -> daemon.StartCPUProfileRequest - 91, // 79: daemon.DaemonService.StopCPUProfile:input_type -> daemon.StopCPUProfileRequest - 93, // 80: daemon.DaemonService.GetInstallerResult:input_type -> daemon.InstallerResultRequest - 95, // 81: daemon.DaemonService.ExposeService:input_type -> daemon.ExposeServiceRequest - 6, // 82: daemon.DaemonService.Login:output_type -> daemon.LoginResponse - 8, // 83: daemon.DaemonService.WaitSSOLogin:output_type -> daemon.WaitSSOLoginResponse - 10, // 84: daemon.DaemonService.Up:output_type -> daemon.UpResponse - 12, // 85: daemon.DaemonService.Status:output_type -> daemon.StatusResponse - 12, // 86: daemon.DaemonService.SubscribeStatus:output_type -> daemon.StatusResponse - 14, // 87: daemon.DaemonService.Down:output_type -> daemon.DownResponse - 16, // 88: daemon.DaemonService.GetConfig:output_type -> daemon.GetConfigResponse - 27, // 89: daemon.DaemonService.ListNetworks:output_type -> daemon.ListNetworksResponse - 29, // 90: daemon.DaemonService.SelectNetworks:output_type -> daemon.SelectNetworksResponse - 29, // 91: daemon.DaemonService.DeselectNetworks:output_type -> daemon.SelectNetworksResponse - 34, // 92: daemon.DaemonService.ForwardingRules:output_type -> daemon.ForwardingRulesResponse - 36, // 93: daemon.DaemonService.DebugBundle:output_type -> daemon.DebugBundleResponse - 38, // 94: daemon.DaemonService.GetLogLevel:output_type -> daemon.GetLogLevelResponse - 40, // 95: daemon.DaemonService.SetLogLevel:output_type -> daemon.SetLogLevelResponse - 43, // 96: daemon.DaemonService.ListStates:output_type -> daemon.ListStatesResponse - 45, // 97: daemon.DaemonService.CleanState:output_type -> daemon.CleanStateResponse - 47, // 98: daemon.DaemonService.DeleteState:output_type -> daemon.DeleteStateResponse - 49, // 99: daemon.DaemonService.SetSyncResponsePersistence:output_type -> daemon.SetSyncResponsePersistenceResponse - 53, // 100: daemon.DaemonService.TracePacket:output_type -> daemon.TracePacketResponse - 99, // 101: daemon.DaemonService.StartCapture:output_type -> daemon.CapturePacket - 101, // 102: daemon.DaemonService.StartBundleCapture:output_type -> daemon.StartBundleCaptureResponse - 103, // 103: daemon.DaemonService.StopBundleCapture:output_type -> daemon.StopBundleCaptureResponse - 55, // 104: daemon.DaemonService.SubscribeEvents:output_type -> daemon.SystemEvent - 57, // 105: daemon.DaemonService.GetEvents:output_type -> daemon.GetEventsResponse - 59, // 106: daemon.DaemonService.SwitchProfile:output_type -> daemon.SwitchProfileResponse - 61, // 107: daemon.DaemonService.SetConfig:output_type -> daemon.SetConfigResponse - 63, // 108: daemon.DaemonService.AddProfile:output_type -> daemon.AddProfileResponse - 65, // 109: daemon.DaemonService.RemoveProfile:output_type -> daemon.RemoveProfileResponse - 67, // 110: daemon.DaemonService.ListProfiles:output_type -> daemon.ListProfilesResponse - 70, // 111: daemon.DaemonService.GetActiveProfile:output_type -> daemon.GetActiveProfileResponse - 72, // 112: daemon.DaemonService.Logout:output_type -> daemon.LogoutResponse - 74, // 113: daemon.DaemonService.GetFeatures:output_type -> daemon.GetFeaturesResponse - 76, // 114: daemon.DaemonService.TriggerUpdate:output_type -> daemon.TriggerUpdateResponse - 78, // 115: daemon.DaemonService.GetPeerSSHHostKey:output_type -> daemon.GetPeerSSHHostKeyResponse - 80, // 116: daemon.DaemonService.RequestJWTAuth:output_type -> daemon.RequestJWTAuthResponse - 82, // 117: daemon.DaemonService.WaitJWTToken:output_type -> daemon.WaitJWTTokenResponse - 84, // 118: daemon.DaemonService.RequestExtendAuthSession:output_type -> daemon.RequestExtendAuthSessionResponse - 86, // 119: daemon.DaemonService.WaitExtendAuthSession:output_type -> daemon.WaitExtendAuthSessionResponse - 88, // 120: daemon.DaemonService.DismissSessionWarning:output_type -> daemon.DismissSessionWarningResponse - 90, // 121: daemon.DaemonService.StartCPUProfile:output_type -> daemon.StartCPUProfileResponse - 92, // 122: daemon.DaemonService.StopCPUProfile:output_type -> daemon.StopCPUProfileResponse - 94, // 123: daemon.DaemonService.GetInstallerResult:output_type -> daemon.InstallerResultResponse - 96, // 124: daemon.DaemonService.ExposeService:output_type -> daemon.ExposeServiceEvent - 82, // [82:125] is the sub-list for method output_type - 39, // [39:82] is the sub-list for method input_type + 44, // 53: daemon.DaemonService.ListStates:input_type -> daemon.ListStatesRequest + 46, // 54: daemon.DaemonService.CleanState:input_type -> daemon.CleanStateRequest + 48, // 55: daemon.DaemonService.DeleteState:input_type -> daemon.DeleteStateRequest + 50, // 56: daemon.DaemonService.SetSyncResponsePersistence:input_type -> daemon.SetSyncResponsePersistenceRequest + 53, // 57: daemon.DaemonService.TracePacket:input_type -> daemon.TracePacketRequest + 100, // 58: daemon.DaemonService.StartCapture:input_type -> daemon.StartCaptureRequest + 102, // 59: daemon.DaemonService.StartBundleCapture:input_type -> daemon.StartBundleCaptureRequest + 104, // 60: daemon.DaemonService.StopBundleCapture:input_type -> daemon.StopBundleCaptureRequest + 56, // 61: daemon.DaemonService.SubscribeEvents:input_type -> daemon.SubscribeRequest + 58, // 62: daemon.DaemonService.GetEvents:input_type -> daemon.GetEventsRequest + 41, // 63: daemon.DaemonService.RegisterUILog:input_type -> daemon.RegisterUILogRequest + 60, // 64: daemon.DaemonService.SwitchProfile:input_type -> daemon.SwitchProfileRequest + 62, // 65: daemon.DaemonService.SetConfig:input_type -> daemon.SetConfigRequest + 64, // 66: daemon.DaemonService.AddProfile:input_type -> daemon.AddProfileRequest + 66, // 67: daemon.DaemonService.RemoveProfile:input_type -> daemon.RemoveProfileRequest + 68, // 68: daemon.DaemonService.ListProfiles:input_type -> daemon.ListProfilesRequest + 71, // 69: daemon.DaemonService.GetActiveProfile:input_type -> daemon.GetActiveProfileRequest + 73, // 70: daemon.DaemonService.Logout:input_type -> daemon.LogoutRequest + 75, // 71: daemon.DaemonService.GetFeatures:input_type -> daemon.GetFeaturesRequest + 77, // 72: daemon.DaemonService.TriggerUpdate:input_type -> daemon.TriggerUpdateRequest + 79, // 73: daemon.DaemonService.GetPeerSSHHostKey:input_type -> daemon.GetPeerSSHHostKeyRequest + 81, // 74: daemon.DaemonService.RequestJWTAuth:input_type -> daemon.RequestJWTAuthRequest + 83, // 75: daemon.DaemonService.WaitJWTToken:input_type -> daemon.WaitJWTTokenRequest + 85, // 76: daemon.DaemonService.RequestExtendAuthSession:input_type -> daemon.RequestExtendAuthSessionRequest + 87, // 77: daemon.DaemonService.WaitExtendAuthSession:input_type -> daemon.WaitExtendAuthSessionRequest + 89, // 78: daemon.DaemonService.DismissSessionWarning:input_type -> daemon.DismissSessionWarningRequest + 91, // 79: daemon.DaemonService.StartCPUProfile:input_type -> daemon.StartCPUProfileRequest + 93, // 80: daemon.DaemonService.StopCPUProfile:input_type -> daemon.StopCPUProfileRequest + 95, // 81: daemon.DaemonService.GetInstallerResult:input_type -> daemon.InstallerResultRequest + 97, // 82: daemon.DaemonService.ExposeService:input_type -> daemon.ExposeServiceRequest + 6, // 83: daemon.DaemonService.Login:output_type -> daemon.LoginResponse + 8, // 84: daemon.DaemonService.WaitSSOLogin:output_type -> daemon.WaitSSOLoginResponse + 10, // 85: daemon.DaemonService.Up:output_type -> daemon.UpResponse + 12, // 86: daemon.DaemonService.Status:output_type -> daemon.StatusResponse + 12, // 87: daemon.DaemonService.SubscribeStatus:output_type -> daemon.StatusResponse + 14, // 88: daemon.DaemonService.Down:output_type -> daemon.DownResponse + 16, // 89: daemon.DaemonService.GetConfig:output_type -> daemon.GetConfigResponse + 27, // 90: daemon.DaemonService.ListNetworks:output_type -> daemon.ListNetworksResponse + 29, // 91: daemon.DaemonService.SelectNetworks:output_type -> daemon.SelectNetworksResponse + 29, // 92: daemon.DaemonService.DeselectNetworks:output_type -> daemon.SelectNetworksResponse + 34, // 93: daemon.DaemonService.ForwardingRules:output_type -> daemon.ForwardingRulesResponse + 36, // 94: daemon.DaemonService.DebugBundle:output_type -> daemon.DebugBundleResponse + 38, // 95: daemon.DaemonService.GetLogLevel:output_type -> daemon.GetLogLevelResponse + 40, // 96: daemon.DaemonService.SetLogLevel:output_type -> daemon.SetLogLevelResponse + 45, // 97: daemon.DaemonService.ListStates:output_type -> daemon.ListStatesResponse + 47, // 98: daemon.DaemonService.CleanState:output_type -> daemon.CleanStateResponse + 49, // 99: daemon.DaemonService.DeleteState:output_type -> daemon.DeleteStateResponse + 51, // 100: daemon.DaemonService.SetSyncResponsePersistence:output_type -> daemon.SetSyncResponsePersistenceResponse + 55, // 101: daemon.DaemonService.TracePacket:output_type -> daemon.TracePacketResponse + 101, // 102: daemon.DaemonService.StartCapture:output_type -> daemon.CapturePacket + 103, // 103: daemon.DaemonService.StartBundleCapture:output_type -> daemon.StartBundleCaptureResponse + 105, // 104: daemon.DaemonService.StopBundleCapture:output_type -> daemon.StopBundleCaptureResponse + 57, // 105: daemon.DaemonService.SubscribeEvents:output_type -> daemon.SystemEvent + 59, // 106: daemon.DaemonService.GetEvents:output_type -> daemon.GetEventsResponse + 42, // 107: daemon.DaemonService.RegisterUILog:output_type -> daemon.RegisterUILogResponse + 61, // 108: daemon.DaemonService.SwitchProfile:output_type -> daemon.SwitchProfileResponse + 63, // 109: daemon.DaemonService.SetConfig:output_type -> daemon.SetConfigResponse + 65, // 110: daemon.DaemonService.AddProfile:output_type -> daemon.AddProfileResponse + 67, // 111: daemon.DaemonService.RemoveProfile:output_type -> daemon.RemoveProfileResponse + 69, // 112: daemon.DaemonService.ListProfiles:output_type -> daemon.ListProfilesResponse + 72, // 113: daemon.DaemonService.GetActiveProfile:output_type -> daemon.GetActiveProfileResponse + 74, // 114: daemon.DaemonService.Logout:output_type -> daemon.LogoutResponse + 76, // 115: daemon.DaemonService.GetFeatures:output_type -> daemon.GetFeaturesResponse + 78, // 116: daemon.DaemonService.TriggerUpdate:output_type -> daemon.TriggerUpdateResponse + 80, // 117: daemon.DaemonService.GetPeerSSHHostKey:output_type -> daemon.GetPeerSSHHostKeyResponse + 82, // 118: daemon.DaemonService.RequestJWTAuth:output_type -> daemon.RequestJWTAuthResponse + 84, // 119: daemon.DaemonService.WaitJWTToken:output_type -> daemon.WaitJWTTokenResponse + 86, // 120: daemon.DaemonService.RequestExtendAuthSession:output_type -> daemon.RequestExtendAuthSessionResponse + 88, // 121: daemon.DaemonService.WaitExtendAuthSession:output_type -> daemon.WaitExtendAuthSessionResponse + 90, // 122: daemon.DaemonService.DismissSessionWarning:output_type -> daemon.DismissSessionWarningResponse + 92, // 123: daemon.DaemonService.StartCPUProfile:output_type -> daemon.StartCPUProfileResponse + 94, // 124: daemon.DaemonService.StopCPUProfile:output_type -> daemon.StopCPUProfileResponse + 96, // 125: daemon.DaemonService.GetInstallerResult:output_type -> daemon.InstallerResultResponse + 98, // 126: daemon.DaemonService.ExposeService:output_type -> daemon.ExposeServiceEvent + 83, // [83:127] is the sub-list for method output_type + 39, // [39:83] is the sub-list for method input_type 39, // [39:39] is the sub-list for extension type_name 39, // [39:39] is the sub-list for extension extendee 0, // [0:39] is the sub-list for field type_name @@ -7483,14 +7571,14 @@ func file_daemon_proto_init() { (*PortInfo_Port)(nil), (*PortInfo_Range_)(nil), } - file_daemon_proto_msgTypes[47].OneofWrappers = []any{} - file_daemon_proto_msgTypes[48].OneofWrappers = []any{} - file_daemon_proto_msgTypes[54].OneofWrappers = []any{} + file_daemon_proto_msgTypes[49].OneofWrappers = []any{} + file_daemon_proto_msgTypes[50].OneofWrappers = []any{} file_daemon_proto_msgTypes[56].OneofWrappers = []any{} - file_daemon_proto_msgTypes[67].OneofWrappers = []any{} - file_daemon_proto_msgTypes[75].OneofWrappers = []any{} - file_daemon_proto_msgTypes[79].OneofWrappers = []any{} - file_daemon_proto_msgTypes[92].OneofWrappers = []any{ + file_daemon_proto_msgTypes[58].OneofWrappers = []any{} + file_daemon_proto_msgTypes[69].OneofWrappers = []any{} + file_daemon_proto_msgTypes[77].OneofWrappers = []any{} + file_daemon_proto_msgTypes[81].OneofWrappers = []any{} + file_daemon_proto_msgTypes[94].OneofWrappers = []any{ (*ExposeServiceEvent_Ready)(nil), } type x struct{} @@ -7499,7 +7587,7 @@ func file_daemon_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_daemon_proto_rawDesc), len(file_daemon_proto_rawDesc)), NumEnums: 4, - NumMessages: 103, + NumMessages: 105, NumExtensions: 0, NumServices: 1, }, diff --git a/client/proto/daemon.proto b/client/proto/daemon.proto index 01d35d5c0..0b95e0811 100644 --- a/client/proto/daemon.proto +++ b/client/proto/daemon.proto @@ -85,6 +85,11 @@ service DaemonService { rpc GetEvents(GetEventsRequest) returns (GetEventsResponse) {} + // RegisterUILog records the desktop UI's absolute log path so the daemon's + // debug bundle can collect it (the daemon runs as root and can't resolve the + // user's config dir). + rpc RegisterUILog(RegisterUILogRequest) returns (RegisterUILogResponse) {} + rpc SwitchProfile(SwitchProfileRequest) returns (SwitchProfileResponse) {} rpc SetConfig(SetConfigRequest) returns (SetConfigResponse) {} @@ -547,6 +552,13 @@ message SetLogLevelRequest { message SetLogLevelResponse { } +message RegisterUILogRequest { + string path = 1; +} + +message RegisterUILogResponse { +} + // State represents a daemon state entry message State { string name = 1; diff --git a/client/proto/daemon_grpc.pb.go b/client/proto/daemon_grpc.pb.go index 72ce14b19..7a4e1201f 100644 --- a/client/proto/daemon_grpc.pb.go +++ b/client/proto/daemon_grpc.pb.go @@ -68,6 +68,10 @@ type DaemonServiceClient interface { StopBundleCapture(ctx context.Context, in *StopBundleCaptureRequest, opts ...grpc.CallOption) (*StopBundleCaptureResponse, error) SubscribeEvents(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (DaemonService_SubscribeEventsClient, error) GetEvents(ctx context.Context, in *GetEventsRequest, opts ...grpc.CallOption) (*GetEventsResponse, error) + // RegisterUILog records the desktop UI's absolute log path so the daemon's + // debug bundle can collect it (the daemon runs as root and can't resolve the + // user's config dir). + RegisterUILog(ctx context.Context, in *RegisterUILogRequest, opts ...grpc.CallOption) (*RegisterUILogResponse, error) SwitchProfile(ctx context.Context, in *SwitchProfileRequest, opts ...grpc.CallOption) (*SwitchProfileResponse, error) SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*SetConfigResponse, error) AddProfile(ctx context.Context, in *AddProfileRequest, opts ...grpc.CallOption) (*AddProfileResponse, error) @@ -404,6 +408,15 @@ func (c *daemonServiceClient) GetEvents(ctx context.Context, in *GetEventsReques return out, nil } +func (c *daemonServiceClient) RegisterUILog(ctx context.Context, in *RegisterUILogRequest, opts ...grpc.CallOption) (*RegisterUILogResponse, error) { + out := new(RegisterUILogResponse) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/RegisterUILog", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *daemonServiceClient) SwitchProfile(ctx context.Context, in *SwitchProfileRequest, opts ...grpc.CallOption) (*SwitchProfileResponse, error) { out := new(SwitchProfileResponse) err := c.cc.Invoke(ctx, "/daemon.DaemonService/SwitchProfile", in, out, opts...) @@ -652,6 +665,10 @@ type DaemonServiceServer interface { StopBundleCapture(context.Context, *StopBundleCaptureRequest) (*StopBundleCaptureResponse, error) SubscribeEvents(*SubscribeRequest, DaemonService_SubscribeEventsServer) error GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error) + // RegisterUILog records the desktop UI's absolute log path so the daemon's + // debug bundle can collect it (the daemon runs as root and can't resolve the + // user's config dir). + RegisterUILog(context.Context, *RegisterUILogRequest) (*RegisterUILogResponse, error) SwitchProfile(context.Context, *SwitchProfileRequest) (*SwitchProfileResponse, error) SetConfig(context.Context, *SetConfigRequest) (*SetConfigResponse, error) AddProfile(context.Context, *AddProfileRequest) (*AddProfileResponse, error) @@ -772,6 +789,9 @@ func (UnimplementedDaemonServiceServer) SubscribeEvents(*SubscribeRequest, Daemo func (UnimplementedDaemonServiceServer) GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetEvents not implemented") } +func (UnimplementedDaemonServiceServer) RegisterUILog(context.Context, *RegisterUILogRequest) (*RegisterUILogResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RegisterUILog not implemented") +} func (UnimplementedDaemonServiceServer) SwitchProfile(context.Context, *SwitchProfileRequest) (*SwitchProfileResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SwitchProfile not implemented") } @@ -1283,6 +1303,24 @@ func _DaemonService_GetEvents_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _DaemonService_RegisterUILog_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RegisterUILogRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DaemonServiceServer).RegisterUILog(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/daemon.DaemonService/RegisterUILog", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DaemonServiceServer).RegisterUILog(ctx, req.(*RegisterUILogRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _DaemonService_SwitchProfile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(SwitchProfileRequest) if err := dec(in); err != nil { @@ -1719,6 +1757,10 @@ var DaemonService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetEvents", Handler: _DaemonService_GetEvents_Handler, }, + { + MethodName: "RegisterUILog", + Handler: _DaemonService_RegisterUILog_Handler, + }, { MethodName: "SwitchProfile", Handler: _DaemonService_SwitchProfile_Handler, diff --git a/client/proto/metadata.go b/client/proto/metadata.go new file mode 100644 index 000000000..10a3187bd --- /dev/null +++ b/client/proto/metadata.go @@ -0,0 +1,30 @@ +package proto + +// SystemEvent metadata markers. The daemon stamps these on internal control +// events it publishes over SubscribeEvents (profile-list refresh, log-level +// change); the desktop UI recognises them and acts on them instead of +// surfacing them as user-facing notifications. +// +// These live in the proto package — the shared contract both the daemon +// (client/server) and the UI (client/ui/services) already import — so producer +// and consumer reference the same constant rather than duplicating literals. +// This file is hand-written and not touched by protoc. +const ( + // MetadataKindKey is the SystemEvent.metadata key carrying the event-kind + // marker (one of the MetadataKind* values below). + MetadataKindKey = "kind" + + // MetadataKindProfileListChanged marks a CLI-driven profile add/remove that + // should nudge the UI's profile views to refresh. + MetadataKindProfileListChanged = "profile-list-changed" + // MetadataKindLogLevelChanged marks a daemon log-level change (or the + // per-subscription snapshot) that drives the GUI's file logging on/off. + MetadataKindLogLevelChanged = "log-level-changed" + + // MetadataProfileKey carries the profile name for + // MetadataKindProfileListChanged. + MetadataProfileKey = "profile" + // MetadataLevelKey carries the lowercase logrus level name for + // MetadataKindLogLevelChanged. + MetadataLevelKey = "level" +) diff --git a/client/server/debug.go b/client/server/debug.go index e754743bd..0b6ac4b53 100644 --- a/client/server/debug.go +++ b/client/server/debug.go @@ -67,6 +67,7 @@ func (s *Server) DebugBundle(_ context.Context, req *proto.DebugBundleRequest) ( StatusRecorder: s.statusRecorder, SyncResponse: syncResponse, LogPath: s.logFile, + UILogPath: s.uiLogPath, CPUProfile: cpuProfileData, CapturePath: capturePath, RefreshStatus: refreshStatus, @@ -127,9 +128,26 @@ func (s *Server) SetLogLevel(_ context.Context, req *proto.SetLogLevelRequest) ( log.Infof("Log level set to %s", level.String()) + // Signal the desktop UI so it can attach/detach its gui-client.log. Rides + // the SubscribeEvents stream as a marked event (see publishLogLevelChanged). + s.publishLogLevelChanged(level.String()) + return &proto.SetLogLevelResponse{}, nil } +// RegisterUILog records the desktop UI's absolute log path so DebugBundle can +// collect the GUI log. The daemon runs as root and can't resolve the user's +// config dir, so the UI reports it. Last-writer-wins (one UI per socket). +func (s *Server) RegisterUILog(_ context.Context, req *proto.RegisterUILogRequest) (*proto.RegisterUILogResponse, error) { + s.mutex.Lock() + defer s.mutex.Unlock() + + s.uiLogPath = req.GetPath() + log.Infof("registered UI log path: %s", s.uiLogPath) + + return &proto.RegisterUILogResponse{}, nil +} + // SetSyncResponsePersistence sets the sync response persistence for the server. func (s *Server) SetSyncResponsePersistence(_ context.Context, req *proto.SetSyncResponsePersistenceRequest) (*proto.SetSyncResponsePersistenceResponse, error) { s.mutex.Lock() diff --git a/client/server/event.go b/client/server/event.go index d93151c96..753a051e7 100644 --- a/client/server/event.go +++ b/client/server/event.go @@ -1,7 +1,9 @@ package server import ( + "github.com/google/uuid" log "github.com/sirupsen/logrus" + "google.golang.org/protobuf/types/known/timestamppb" "github.com/netbirdio/netbird/client/proto" ) @@ -16,6 +18,15 @@ func (s *Server) SubscribeEvents(req *proto.SubscribeRequest, stream proto.Daemo log.Debug("client subscribed to events") s.startUpdateManagerForGUI() + // Replay the current log level to this subscriber so a freshly-connected UI + // learns it even when the daemon was already started with --log-level debug + // (the change-driven publishLogLevelChanged only fires on SetLogLevel). Sent + // directly on this stream rather than via PublishEvent so it reaches only + // the new subscriber, not every connected client. + if err := s.sendCurrentLogLevel(stream); err != nil { + return err + } + for { select { case event := <-subscription.Events(): @@ -28,3 +39,24 @@ func (s *Server) SubscribeEvents(req *proto.SubscribeRequest, stream proto.Daemo } } } + +// sendCurrentLogLevel sends a marked log-level-changed SystemEvent carrying the +// daemon's current level directly to one subscriber. Mirrors the shape +// publishLogLevelChanged emits so the UI's dispatchSystemEvent handles both the +// same way. +func (s *Server) sendCurrentLogLevel(stream proto.DaemonService_SubscribeEventsServer) error { + level := log.GetLevel().String() + event := &proto.SystemEvent{ + Id: uuid.New().String(), + Severity: proto.SystemEvent_INFO, + Category: proto.SystemEvent_SYSTEM, + Message: "Log level changed", + Metadata: map[string]string{proto.MetadataKindKey: proto.MetadataKindLogLevelChanged, proto.MetadataLevelKey: level}, + Timestamp: timestamppb.Now(), + } + if err := stream.Send(event); err != nil { + log.Warnf("error sending initial log level event: %v", err) + return err + } + return nil +} diff --git a/client/server/server.go b/client/server/server.go index 20f80743e..9fa3bf507 100644 --- a/client/server/server.go +++ b/client/server/server.go @@ -67,6 +67,12 @@ type Server struct { logFile string + // uiLogPath is the desktop UI's absolute log path, reported via + // RegisterUILog. Guarded by mutex. Consumed by DebugBundle so the bundle + // can collect the GUI log even though the daemon runs as root and can't + // resolve the user's config dir. Last-writer-wins (one UI per socket). + uiLogPath string + oauthAuthFlow oauthAuthFlow // extendAuthSessionFlow holds the pending PKCE flow created by // RequestExtendAuthSession until WaitExtendAuthSession resolves it. @@ -1916,8 +1922,8 @@ func (s *Server) RemoveProfile(ctx context.Context, msg *proto.RemoveProfileRequ // a marked INFO/SYSTEM event over SubscribeEvents: the UI's dispatchSystemEvent // recognises the metadata "kind" marker and translates it into its internal // profile-changed signal that both the tray menu and the React profile views -// already subscribe to (see client/ui/services/daemon_feed.go, -// MetadataKindProfileListChanged). userMessage is intentionally empty so this +// already subscribe to (see proto.MetadataKindProfileListChanged, recognised in +// client/ui/services/daemon_feed.go). userMessage is intentionally empty so this // stays a silent refresh signal rather than a user-facing notification. func (s *Server) publishProfileListChanged(profileName string) { s.statusRecorder.PublishEvent( @@ -1925,7 +1931,26 @@ func (s *Server) publishProfileListChanged(profileName string) { proto.SystemEvent_SYSTEM, "Profile list changed", "", - map[string]string{"kind": "profile-list-changed", "profile": profileName}, + map[string]string{proto.MetadataKindKey: proto.MetadataKindProfileListChanged, proto.MetadataProfileKey: profileName}, + ) +} + +// publishLogLevelChanged signals the desktop UI that the daemon log level +// changed, so it can attach/detach its rotated gui-client.log. Like +// publishProfileListChanged, this rides the SubscribeEvents stream as a marked +// INFO/SYSTEM event (kind "log-level-changed", level the lowercase logrus +// name); the UI's dispatchSystemEvent recognises the marker and routes it to +// the logging toggle instead of an OS toast (userMessage is empty so it stays +// a silent control signal). The "level" value matches log.Level.String() +// (e.g. "debug", "info") so the UI can parse it directly. See +// proto.MetadataKindLogLevelChanged, recognised in client/ui/services/daemon_feed.go. +func (s *Server) publishLogLevelChanged(level string) { + s.statusRecorder.PublishEvent( + proto.SystemEvent_INFO, + proto.SystemEvent_SYSTEM, + "Log level changed", + "", + map[string]string{proto.MetadataKindKey: proto.MetadataKindLogLevelChanged, proto.MetadataLevelKey: level}, ) } diff --git a/client/ui/CLAUDE.md b/client/ui/CLAUDE.md index a1b8bcb0d..db2e2bdb2 100644 --- a/client/ui/CLAUDE.md +++ b/client/ui/CLAUDE.md @@ -7,7 +7,7 @@ This is the Wails v3 desktop UI for NetBird. Go services live in `services/`; th ## Layout ### Go (top-level package `main`) -- `main.go` — app entry. Builds the shared gRPC `Conn`, constructs services, registers them with Wails, creates the main webview window, then starts (in order) the Linux SNI watcher → tray → `peers.Watch` → `app.Run`. CLI flags: `--daemon-addr`, `--log-file` (repeatable; first user-provided value drops the seeded `console` default), `--log-level` (`trace|debug|info|warn|error`, default `info`). +- `main.go` — app entry. Builds the shared gRPC `Conn`, constructs services, registers them with Wails, creates the main webview window, then starts (in order) the Linux SNI watcher → tray → `peers.Watch` → `app.Run`. CLI flags: `--daemon-addr`, `--log-file` (repeatable; default is **empty** so "no flag" is distinguishable from explicit `--log-file console` — when empty `parseFlagsAndInitLog` falls back to `console` for `InitLog` and returns `userSetLogFile=false`), `--log-level` (`trace|debug|info|warn|error`, default `info`). See "GUI debug logging" below for what `userSetLogFile` gates. - `tray.go` — `Tray` struct + menu. Subscribes to `EventStatus`, `EventSystem`, `EventUpdateAvailable`, `EventUpdateProgress`. Owns per-status icon/dot, Profiles submenu, Connect/Disconnect swap, About → Update, session-expired toast. - **Tray menu updates go through `relayoutMenu` (whole-tree rebuild), never in-place submenu mutation.** Any dynamic menu change — Profiles submenu (`tray_profiles.go loadProfiles` → caches rows under `profilesMu`, then `fillProfileSubmenu`), Exit Node submenu (`tray_exitnodes.go refreshExitNodes` → `fillExitNodeSubmenu`), daemon-version row (`tray_status.go`), and the About → Update row (`tray_update.go applyState` → `onMenuChange` callback) — rebuilds the entire menu via `Tray.relayoutMenu` (`buildMenu()` + repaint cached state + single `t.tray.SetMenu`). Serialised by `menuMu`. **Why:** on KDE/Plasma the StatusNotifierItem host caches a submenu's layout the first time it's opened (`GetLayout` for that submenu id) and never re-fetches it on a `LayoutUpdated(parent=0)` signal — so the old `submenu.Clear()`+`Add()` left both the visible rows AND the click→id mapping frozen on the first snapshot. Because `Clear()`+`Add()` allocates fresh monotonic item ids each time (Wails `menuitem.go`), clicks then sent ids the rebuilt `itemMap` no longer knew, and silently no-op'd ("Manage Profiles" stopped responding after the first switch). `buildMenu()` allocates a brand-new submenu container id each relayout, which Plasma treats as unseen and re-queries on next open — fixing both the stale paint and the dead clicks. Confirmed via `dbus-monitor`: a re-opened submenu issued no `GetLayout` until its container id changed. The whole-tree `SetMenu` also subsumes the older darwin detached-NSMenu workaround. `fill*Submenu` helpers are pure UI (read caches, no daemon fetch, no `SetMenu`) so `relayoutMenu` never recurses back into the fetchers. - `tray_linux.go` — `init()` sets `WEBKIT_DISABLE_DMABUF_RENDERER=1` (blank-white window on VMs / minimal WMs) and `WEBKIT_DISABLE_COMPOSITING_MODE=1` (Intel/Mesa SIGSEGV in `g_application_run` via unimplemented DRM-format-modifier paths — DMABUF-disable alone doesn't cover the GL compositor). Both are skipped if the user already set the var. Also `WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS=1` when unprivileged userns are blocked. @@ -35,7 +35,7 @@ All services live in `services/` and assume a build tag `!android && !ios && !fr | `Peers` | `peers.go` | Daemon status snapshot + two long-running streams (`SubscribeStatus` → `EventStatus`, `SubscribeEvents` → `EventSystem`). Emits synthetic `StatusDaemonUnavailable` when the socket is unreachable. Owns the profile-switch suppression filter (`BeginProfileSwitch` / `CancelProfileSwitch` / `shouldSuppress`). Fan-outs update metadata into dedicated `EventUpdateAvailable` / `EventUpdateProgress` events. | | `Networks` | `network.go` | `List` / `Select` / `Deselect` of routed networks. | | `Forwarding` | `forwarding.go` | `List` exposed/forwarded services from the daemon's reverse-proxy table. | -| `Debug` | `debug.go` | `Bundle` (debug bundle creation + optional upload) / `Get|SetLogLevel` / `RevealFile` (cross-platform "show in file manager"). | +| `Debug` | `debug.go` | `Bundle` (debug bundle creation + optional upload) / `Get|SetLogLevel` / `RegisterUILog` (report the GUI log path to the daemon for bundle collection) / `RevealFile` (cross-platform "show in file manager"). | | `Update` | `update.go` | `GetState` / `Trigger` (enforced installer) / `GetInstallerResult` / `Quit`. The install-progress UI lives in its own auxiliary window (`/#/dialog/install-progress`), opened by `WindowManager.OpenInstallProgress` — the daemon goes unreachable mid-install so it can't be inside the main window. | | `WindowManager` | `windowmanager.go` | `OpenSettings(tab)` / `OpenBrowserLogin(uri)` / `CloseBrowserLogin` / `OpenSessionExpiration(seconds)` / `CloseSessionExpiration` / `OpenInstallProgress(version)` / `CloseInstallProgress` / `OpenWelcome` / `CloseWelcome` / `OpenError(title, message)` / `CloseError` / `OpenMain`. `OpenSettings("")` opens the General tab; pass a tab id (e.g. `"profiles"`) to deep-link, encoded as `?tab=…` in the start URL. `OpenInstallProgress` is `AlwaysOnTop` and hides every other visible window for the duration of the install (restored on close). `OpenMain` is the handoff path from the welcome window to the main UI (avoids depending on the tray). Auxiliary windows are created on first open and **destroyed** on close (Wails-recommended singleton pattern; prevents the macOS dock-reopen from resurrecting hidden windows). | | `I18n` | `i18n.go` | Thin facade over `i18n.Bundle`. `Languages()` returns the shipped locales (`_index.json`); `Bundle(code)` returns the full key→text map for one language so the React layer can drive its own translation library. | @@ -50,6 +50,17 @@ All services live in `services/` and assume a build tag `!android && !ios && !fr - Pinned versions (see `daemon.pb.go` header): `protoc v7.34.1`, `protoc-gen-go v1.36.6`. CI's `proto-version-check` workflow fails on mismatch. - After proto regen, also regen Wails bindings so the TS layer picks up new fields. +## GUI debug logging + +When the daemon is put into **debug**/**trace** level, the GUI automatically writes a rotated `gui-client.log` in `os.UserConfigDir()/netbird/` and the daemon's **debug bundle** collects it. Pieces: + +- **`uilogpath.go`** (package `main`) — `uiLogPath()` resolves the path; `newDebugLog(userSetLogFile)` builds the `guilog.DebugLog` (disabled when the user passed `--log-file`, or when the config dir can't be resolved). +- **`guilog/debuglog.go` — `guilog.DebugLog`** (own package, **not** a Wails service — no React binding) — owns the file-logging side effects. `Apply(level)`: on debug/trace attaches `gui-client.log` alongside the console (via `util.SetLogOutputs`, MultiWriter, rotated by timberjack like the daemon log) and raises the logrus level; on a higher level detaches the file and restores `info`. Idempotent (`fileOn` guard) so the startup replay + a racing change-event are harmless. The `gui-client.log` is left on disk on quit (rotated by timberjack) for the debug bundle — there's no shutdown cleanup. `Path()` returns "" when disabled so the daemon won't try to collect a file the GUI never writes. +- **Activation rule:** any `--log-file` (even `console`) is a manual override → the controller is disabled and never touches logging. Only the *absence* of `--log-file` enables the daemon-driven `gui-client.log`. This is why `parseFlagsAndInitLog` seeds the flag default empty (Layout note above). +- **Level signalling — no new stream.** The daemon publishes a **marked `SystemEvent`** (`metadata[proto.MetadataKindKey]==proto.MetadataKindLogLevelChanged`, `metadata[proto.MetadataLevelKey]==`) on the existing `SubscribeEvents` stream. `DaemonFeed.dispatchSystemEvent` recognises the marker and routes it to the controller's `Apply` instead of an OS toast (same pattern as `proto.MetadataKindProfileListChanged`). The controller is injected into `NewDaemonFeed` (a `services.LogController` interface — no exported setter, so the Wails-bound `DaemonFeed` gains no binding), and `DaemonFeed` **re-registers the UI log path** (`RegisterUILog` RPC) on every event-stream (re)connect, so a daemon restart re-learns it. Startup case (daemon already in debug) is covered daemon-side: `Server.SubscribeEvents` (`client/server/event.go`) sends the current level once to each new subscriber; `SetLogLevel` publishes on change (`publishLogLevelChanged` in `client/server/server.go`). The metadata key/value markers live in `client/proto/metadata.go` so producer (daemon) and consumer (UI) share one definition. +- **Daemon side of the bundle:** `Server.RegisterUILog` stores the path in `Server.uiLogPath`; `DebugBundle` passes it to `debug.GeneratorDependencies.UILogPath`; `BundleGenerator.addUILog` adds `gui-client.log` + rotated siblings (`addRotatedLogFiles(dir, "gui-client")` — the glob is prefix-parametrised so it doesn't collide with the daemon's own `client*.log.*`). Missing file is non-fatal (the GUI only writes it while in debug). +- **JS-side logs/errors** already reach the same logrus pipeline via `frontend/src/lib/logs.ts` → `services.UILog.Log`, so once the file is attached, frontend console/`unhandledrejection`/`error` output is captured too. Go-side uncaught-goroutine panics go to stderr only (out of scope). + ## Events bus `main.go` registers five typed events for the frontend: `netbird:status` (`Status`), `netbird:event` (`SystemEvent`), `netbird:profile:changed` (`ProfileRef`), `netbird:update:available` (`UpdateAvailable`), `netbird:update:progress` (`UpdateProgress`). `netbird:profile:changed` fires from `ProfileSwitcher.SwitchActive` after a successful daemon-side switch — both the React `ProfileContext` and the tray subscribe so a flip driven from one surface paints in the others (the daemon itself does not emit a profile event). Plus three plain-string events: diff --git a/client/ui/frontend/src/contexts/DebugBundleContext.tsx b/client/ui/frontend/src/contexts/DebugBundleContext.tsx index ea7ddc3b4..c623effc1 100644 --- a/client/ui/frontend/src/contexts/DebugBundleContext.tsx +++ b/client/ui/frontend/src/contexts/DebugBundleContext.tsx @@ -8,6 +8,11 @@ import { useProfile } from "@/contexts/ProfileContext.tsx"; const NETBIRD_UPLOAD_URL = "https://upload.debug.netbird.io/upload-url"; const TRACE_LOG_FILE_COUNT = 5; const PLAIN_LOG_FILE_COUNT = 1; +// Lowercase logrus level name sent to Debug.SetLogLevel (the Go binding +// upper-cases before the proto enum lookup). Raising to trace is what drives +// the daemon's verbose logging and the GUI's gui-client.log during a bundle. +const TRACE_LOG_LEVEL = "trace"; +const DEFAULT_LOG_LEVEL = "info"; export type DebugStage = | { kind: "idle" } @@ -68,7 +73,7 @@ const runTracePhase = async ( // empty } throwIfAborted(signal); - await DebugSvc.SetLogLevel({ level: "trace" }); + await DebugSvc.SetLogLevel({ level: TRACE_LOG_LEVEL }); level.raised = true; throwIfAborted(signal); @@ -123,7 +128,7 @@ const useDebugBundle = () => { const signal = ctrl.signal; const uploadUrl = upload ? NETBIRD_UPLOAD_URL : ""; - const level: LevelState = { original: "info", raised: false }; + const level: LevelState = { original: DEFAULT_LOG_LEVEL, raised: false }; try { if (trace) { diff --git a/client/ui/guilog/debuglog.go b/client/ui/guilog/debuglog.go new file mode 100644 index 000000000..fe24f3be6 --- /dev/null +++ b/client/ui/guilog/debuglog.go @@ -0,0 +1,92 @@ +//go:build !android && !ios && !freebsd && !js + +// Package guilog manages the desktop UI's own file log (gui-client.log), which +// follows the daemon's log level: when the daemon is in debug/trace the GUI +// attaches a rotated file alongside the console so its (and the React frontend's +// forwarded) output is captured for the debug bundle. It is intentionally not a +// Wails service — it has no frontend-facing methods and generates no TS +// bindings — so it lives outside client/ui/services. +package guilog + +import ( + "sync" + + log "github.com/sirupsen/logrus" + + "github.com/netbirdio/netbird/util" +) + +// DebugLog is the daemon-debug-driven GUI file log. The daemon publishes a +// marked "log-level-changed" SystemEvent over SubscribeEvents (both on change +// and once per new subscription, so a daemon already in debug is picked up at +// startup); services.DaemonFeed routes it here via Apply. +// +// When the daemon is in debug/trace and the GUI owns its log (no manual +// --log-file), it attaches a rotated gui-client.log alongside the console and +// raises the logrus level; back to a higher level it detaches the file and +// restores info. The file is left on disk (rotated by timberjack) for the debug +// bundle to collect. When the user set --log-file explicitly, it is disabled and +// never touches logging. +type DebugLog struct { + uiPath string + enabled bool + + mu sync.Mutex + fileOn bool +} + +// NewDebugLog builds the GUI debug log. uiPath is the absolute gui-client.log +// path; enabled is false when the user passed --log-file (manual override), in +// which case it leaves logging untouched. +func NewDebugLog(uiPath string, enabled bool) *DebugLog { + return &DebugLog{uiPath: uiPath, enabled: enabled} +} + +// Path returns the GUI log path to register with the daemon, or "" when the GUI +// doesn't own its log (manual --log-file) — in that case the daemon shouldn't +// try to collect a gui-client.log the GUI never writes. +func (d *DebugLog) Path() string { + if !d.enabled { + return "" + } + return d.uiPath +} + +// Apply reacts to a daemon log level (the lowercase logrus name, e.g. "debug"). +// Idempotent: repeated identical levels are no-ops, so the startup replay plus a +// racing change-event do no harm. +func (d *DebugLog) Apply(level string) { + if !d.enabled { + return + } + + // "debug or more verbose" (debug/trace) turns the file log on; anything less + // verbose turns it off. Compare numerically against logrus' own levels so + // there are no hard-coded level-name literals. + lvl, err := log.ParseLevel(level) + if err != nil { + lvl = log.InfoLevel + } + debug := lvl >= log.DebugLevel + + d.mu.Lock() + defer d.mu.Unlock() + + switch { + case debug && !d.fileOn: + if err := util.SetLogOutputs(log.StandardLogger(), util.LogConsole, d.uiPath); err != nil { + log.Errorf("attach GUI file log %s: %v", d.uiPath, err) + return + } + log.SetLevel(lvl) + d.fileOn = true + log.Infof("GUI file logging enabled (daemon level %s), writing to %s", level, d.uiPath) + case !debug && d.fileOn: + if err := util.SetLogOutputs(log.StandardLogger(), util.LogConsole); err != nil { + log.Errorf("detach GUI file log: %v", err) + } + log.SetLevel(log.InfoLevel) + d.fileOn = false + log.Infof("GUI file logging disabled (daemon level: %s)", level) + } +} diff --git a/client/ui/main.go b/client/ui/main.go index afe5f63dd..6c12b57c2 100644 --- a/client/ui/main.go +++ b/client/ui/main.go @@ -84,9 +84,16 @@ func init() { } func main() { - daemonAddr := parseFlagsAndInitLog() + daemonAddr, userSetLogFile := parseFlagsAndInitLog() conn := NewConn(daemonAddr) + // GUI file logging: when the user didn't pass --log-file, the GUI manages a + // gui-client.log that follows the daemon's debug level (attached when the + // daemon is in debug/trace, detached otherwise, rotated by timberjack) and is + // included in the debug bundle. It rides DaemonFeed's SubscribeEvents stream + // (passed into NewDaemonFeed below; see guilog.DebugLog). + debugLog := newDebugLog(userSetLogFile) + // tray is captured in the SingleInstance callback below; the var is // declared before app.New so the closure has a stable reference. var tray *Tray @@ -103,7 +110,7 @@ func main() { // Wails-bound facade over the holder plus the install RPCs. updaterHolder := updater.NewHolder(app.Event) update := services.NewUpdate(conn, updaterHolder) - daemonFeed := services.NewDaemonFeed(conn, app.Event, updaterHolder) + daemonFeed := services.NewDaemonFeed(conn, app.Event, updaterHolder, debugLog) notifier := notifications.New() // macOS won't surface any toast until the app has requested permission; // the request runs after ApplicationStarted so the notifier's Startup has @@ -230,18 +237,30 @@ func requestNotificationAuthorization(notifier *notifications.NotificationServic } // parseFlagsAndInitLog parses the CLI flags, initialises the logger, and -// returns the resolved daemon gRPC address. -func parseFlagsAndInitLog() string { +// returns the resolved daemon gRPC address plus userSetLogFile — true when the +// user passed --log-file explicitly. userSetLogFile is the manual-override +// signal: when true the GUI leaves logging alone (the daemon's debug level +// won't attach gui-client.log); when false the GUI manages a per-session +// gui-client.log driven by the daemon level. The default seed is empty (not +// "console") so "no flag" and an explicit "--log-file console" are +// distinguishable; an empty result falls back to console for InitLog. +func parseFlagsAndInitLog() (string, bool) { daemonAddr := flag.String("daemon-addr", DaemonAddr(), "Daemon gRPC address: unix:///path or tcp://host:port") - logFiles := &stringList{values: []string{"console"}} - flag.Var(logFiles, "log-file", "Log destination. Repeat to log to multiple targets at once, e.g. `--log-file console --log-file Y:/netbird-ui.log`. Each value is one of: console, syslog, or a file path. File destinations are rotated by lumberjack (same as the daemon). Defaults to console.") + logFiles := &stringList{} + flag.Var(logFiles, "log-file", "Log destination. Repeat to log to multiple targets at once, e.g. `--log-file console --log-file Y:/netbird-ui.log`. Each value is one of: console, syslog, or a file path. File destinations are rotated by lumberjack (same as the daemon). Defaults to console. Passing any value disables the daemon-debug-driven gui-client.log.") logLevel := flag.String("log-level", "info", "Log level: trace|debug|info|warn|error.") flag.Parse() - if err := util.InitLog(*logLevel, logFiles.values...); err != nil { + userSetLogFile := len(logFiles.values) > 0 + targets := logFiles.values + if !userSetLogFile { + targets = []string{"console"} + } + + if err := util.InitLog(*logLevel, targets...); err != nil { log.Fatalf("init log: %v", err) } - return *daemonAddr + return *daemonAddr, userSetLogFile } // newApplication constructs the Wails application. onSecondInstance is invoked diff --git a/client/ui/services/daemon_feed.go b/client/ui/services/daemon_feed.go index bc1c24481..92e749283 100644 --- a/client/ui/services/daemon_feed.go +++ b/client/ui/services/daemon_feed.go @@ -46,20 +46,11 @@ const ( // tray (Go side) so the frontend stays passive on this flow. EventSessionWarning = "netbird:session:warning" - // MetadataKindProfileListChanged is the SystemEvent.metadata["kind"] - // marker the daemon stamps on the INFO/SYSTEM event it publishes after a - // CLI-driven AddProfile / RemoveProfile (the daemon emits no dedicated - // profile RPC event). dispatchSystemEvent recognises it and re-emits the - // existing EventProfileChanged so the tray and React profile views refresh - // — closing the gap the SubscribeStatus path can't, since a profile - // add/remove doesn't change the daemon's status string (the tray's - // iconChanged guard would swallow it). The daemon side hard-codes the same - // string literal in client/server/server.go (client/server cannot import - // this UI package). - MetadataKindProfileListChanged = "profile-list-changed" - // metadataKindKey is the SystemEvent.metadata key the "kind" marker lives - // under. Kept in sync with the daemon-side literal in client/server. - metadataKindKey = "kind" + // The SystemEvent.metadata markers the daemon stamps on its internal + // control events live in the shared proto package + // (proto.MetadataKind*/MetadataKindKey/MetadataLevelKey) so producer + // (client/server) and consumer (here) reference the same constants. See + // dispatchSystemEvent for how they're recognised. // StatusDaemonUnavailable is the synthetic Status the UI emits when the // daemon's gRPC socket is unreachable (daemon not running, socket @@ -198,6 +189,13 @@ type DaemonFeed struct { conn DaemonConn emitter Emitter updater *updater.Holder + // logCtl reacts to the daemon's log level (delivered as a marked + // SystemEvent over the same SubscribeEvents stream) by attaching/detaching + // the GUI file log. nil when the GUI doesn't manage its log (server build / + // not wired), in which case the marker is ignored. Held as a narrow + // interface so this package doesn't depend on client/ui/guilog (the concrete + // type lives there; main passes it into NewDaemonFeed). + logCtl LogController mu sync.Mutex cancel context.CancelFunc @@ -217,8 +215,24 @@ type DaemonFeed struct { switchLoginWatchUntil time.Time } -func NewDaemonFeed(conn DaemonConn, emitter Emitter, updaterHolder *updater.Holder) *DaemonFeed { - return &DaemonFeed{conn: conn, emitter: emitter, updater: updaterHolder} +// LogController is the subset of client/ui/guilog.DebugLog that DaemonFeed +// drives: Apply turns the GUI file log on/off for a daemon level, Path is the +// gui-client.log path to register with the daemon (empty when the GUI doesn't +// own its log). Kept as an interface so services doesn't import guilog. The +// daemon delivers log-level changes as marked SystemEvents on the same +// SubscribeEvents stream this feed consumes, so it rides along here rather than +// opening a second daemon subscription. +type LogController interface { + Apply(level string) + Path() string +} + +// NewDaemonFeed builds the feed. logCtl may be nil (server build / GUI log not +// managed), in which case log-level markers on the event stream are ignored. +// Injected at construction rather than via a setter so DaemonFeed (a Wails +// service) exposes no extra method to the binding generator. +func NewDaemonFeed(conn DaemonConn, emitter Emitter, updaterHolder *updater.Holder, logCtl LogController) *DaemonFeed { + return &DaemonFeed{conn: conn, emitter: emitter, updater: updaterHolder, logCtl: logCtl} } // BeginProfileSwitch is called by ProfileSwitcher at the start of a switch @@ -525,6 +539,17 @@ func (s *DaemonFeed) subscribeAndStreamEvents(ctx context.Context) error { if err != nil { return fmt.Errorf("subscribe: %w", err) } + + // Re-register the GUI log path on every (re)connect so a daemon restart + // re-learns it and a later debug bundle still finds the file. Best-effort — + // a failure here must not abort the event stream. Done even when file + // logging is off (enabled but not in debug), so the path is known ahead of + // any debug toggle. + if s.logCtl != nil && s.logCtl.Path() != "" { + if _, err := cli.RegisterUILog(ctx, &proto.RegisterUILogRequest{Path: s.logCtl.Path()}); err != nil { + log.Warnf("register UI log path: %v", err) + } + } for { ev, err := stream.Recv() if err != nil { @@ -549,10 +574,19 @@ func (s *DaemonFeed) dispatchSystemEvent(ev *proto.SystemEvent) { // ProfileContext.refresh already subscribe to) and stop — it's an internal // refresh signal, not a user-facing notification, so it must not reach the // Recent Events list or fire an OS toast. - if se.Metadata[metadataKindKey] == MetadataKindProfileListChanged { + if se.Metadata[proto.MetadataKindKey] == proto.MetadataKindProfileListChanged { s.emitter.Emit(EventProfileChanged, ProfileRef{}) return } + // A marked log-level-changed event drives the GUI file log on/off. It's an + // internal control signal, not a user-facing notification — handle and stop + // so it never reaches the Recent Events list or fires an OS toast. + if se.Metadata[proto.MetadataKindKey] == proto.MetadataKindLogLevelChanged { + if s.logCtl != nil { + s.logCtl.Apply(se.Metadata[proto.MetadataLevelKey]) + } + return + } s.emitter.Emit(EventDaemonNotification, se) if warn, ok := authsession.WarningFromMetadata(se.Metadata); ok { s.emitter.Emit(EventSessionWarning, warn) diff --git a/client/ui/services/debug.go b/client/ui/services/debug.go index 1a129dbc6..64afe38d0 100644 --- a/client/ui/services/debug.go +++ b/client/ui/services/debug.go @@ -8,6 +8,7 @@ import ( "os/exec" "path/filepath" "runtime" + "strings" "github.com/netbirdio/netbird/client/proto" "github.com/netbirdio/netbird/version" @@ -99,12 +100,29 @@ func (s *Debug) RevealFile(_ context.Context, path string) error { return cmd.Start() } +// RegisterUILog tells the daemon the absolute path of the GUI's log file so +// the daemon's debug bundle can collect it (the daemon runs as root and can't +// resolve the user's config dir). Called by LogLevelWatcher on each daemon +// (re)connect. +func (s *Debug) RegisterUILog(ctx context.Context, path string) error { + cli, err := s.conn.Client() + if err != nil { + return err + } + _, err = cli.RegisterUILog(ctx, &proto.RegisterUILogRequest{Path: path}) + return err +} + func (s *Debug) SetLogLevel(ctx context.Context, lvl LogLevel) error { cli, err := s.conn.Client() if err != nil { return err } - level, ok := proto.LogLevel_value[lvl.Level] + // proto.LogLevel_value keys are the enum names (TRACE/DEBUG/INFO/...), but + // callers (the React side, GetLogLevel) use the lowercase logrus names + // ("trace"/"debug"/...). Upper-case before the lookup so a lowercase level + // doesn't silently fall back to INFO. + level, ok := proto.LogLevel_value[strings.ToUpper(lvl.Level)] if !ok { level = int32(proto.LogLevel_INFO) } diff --git a/client/ui/uilogpath.go b/client/ui/uilogpath.go new file mode 100644 index 000000000..bfe80ee7d --- /dev/null +++ b/client/ui/uilogpath.go @@ -0,0 +1,41 @@ +//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) +} diff --git a/util/log.go b/util/log.go index 3896ff6bc..623b11e0f 100644 --- a/util/log.go +++ b/util/log.go @@ -40,6 +40,45 @@ func InitLogger(logger *log.Logger, logLevel string, logs ...string) error { if err != nil { return fmt.Errorf("failed parsing log-level %s: %w", logLevel, err) } + + logFmt, err := buildWriters(logger, logs...) + if err != nil { + return err + } + + switch logFmt { + case "json": + formatter.SetJSONFormatter(logger) + case "syslog": + formatter.SetSyslogFormatter(logger) + default: + formatter.SetTextFormatter(logger) + } + logger.SetLevel(level) + + setGRPCLibLogger(logger) + + return nil +} + +// SetLogOutputs re-points an already-initialized logger to the given targets +// (console/syslog/file), with the same target semantics as InitLogger, but +// without re-parsing the level or resetting the formatter. The desktop GUI uses +// it to attach the rotated gui-client.log alongside the console when the daemon +// enters debug, and drop back to console-only when it leaves. +func SetLogOutputs(logger *log.Logger, logs ...string) error { + if _, err := buildWriters(logger, logs...); err != nil { + return err + } + setGRPCLibLogger(logger) + return nil +} + +// buildWriters resolves the given log targets to writers and points the logger +// at them (single writer or MultiWriter). It returns the log format implied by +// the targets (syslog forces "syslog"; otherwise the NB_LOG_FORMAT env value). +// Shared by InitLogger and SetLogOutputs. +func buildWriters(logger *log.Logger, logs ...string) (string, error) { var writers []io.Writer logFmt := os.Getenv("NB_LOG_FORMAT") @@ -61,7 +100,7 @@ func InitLogger(logger *log.Logger, logLevel string, logs ...string) error { default: writer, err := setupLogFile(logPath, isRotationDisabled(logger)) if err != nil { - return fmt.Errorf("failed setting up log file: %s, %w", logPath, err) + return "", fmt.Errorf("failed setting up log file: %s, %w", logPath, err) } writers = append(writers, writer) } @@ -73,19 +112,7 @@ func InitLogger(logger *log.Logger, logLevel string, logs ...string) error { logger.SetOutput(writers[0]) } - switch logFmt { - case "json": - formatter.SetJSONFormatter(logger) - case "syslog": - formatter.SetSyslogFormatter(logger) - default: - formatter.SetTextFormatter(logger) - } - logger.SetLevel(level) - - setGRPCLibLogger(logger) - - return nil + return logFmt, nil } // FindFirstLogPath returns the first logs entry that could be a log path, that is neither empty, nor a special value