From a32056dca10973db5da78cdb050be7cddfbe6e94 Mon Sep 17 00:00:00 2001 From: Wolfgang Welz <welzwo@gmail.com> Date: Wed, 8 Jan 2020 22:55:42 +0100 Subject: [PATCH] fix: log to console if status screen is not running --- config.json | 5 +- plugins/statusscreen/constants.go | 7 -- plugins/statusscreen/logger.go | 58 ++++++++++++----- plugins/statusscreen/plugin.go | 81 +++++++++++++++++++++++ plugins/statusscreen/status_message.go | 14 ---- plugins/statusscreen/statusscreen.go | 90 ++++++-------------------- plugins/statusscreen/ui_log.go | 15 ----- plugins/statusscreen/ui_log_entry.go | 12 ++-- 8 files changed, 150 insertions(+), 132 deletions(-) delete mode 100644 plugins/statusscreen/constants.go create mode 100644 plugins/statusscreen/plugin.go delete mode 100644 plugins/statusscreen/status_message.go delete mode 100644 plugins/statusscreen/ui_log.go diff --git a/config.json b/config.json index 1b885d18..8550f628 100644 --- a/config.json +++ b/config.json @@ -23,9 +23,8 @@ "DisableStacktrace":false, "Encoding":"console", "OutputPaths":[ - "stdout" - ], - "DisableEvents":false + "shimmer.log" + ] }, "node":{ "disableplugins":"", diff --git a/plugins/statusscreen/constants.go b/plugins/statusscreen/constants.go deleted file mode 100644 index 1fa6c46d..00000000 --- a/plugins/statusscreen/constants.go +++ /dev/null @@ -1,7 +0,0 @@ -package statusscreen - -import "time" - -const ( - REPAINT_INTERVAL = 500 * time.Millisecond -) diff --git a/plugins/statusscreen/logger.go b/plugins/statusscreen/logger.go index 5d9d780b..10606990 100644 --- a/plugins/statusscreen/logger.go +++ b/plugins/statusscreen/logger.go @@ -1,31 +1,55 @@ package statusscreen import ( + stdlog "log" + "sync" "time" "github.com/iotaledger/hive.go/logger" ) -func storeStatusMessage(logLevel logger.Level, prefix string, message string) { - mutex.Lock() - defer mutex.Unlock() - messageLog = append(messageLog, &StatusMessage{ - Source: prefix, - LogLevel: logLevel, - Message: message, - Time: time.Now(), +var ( + mu sync.Mutex + logMessages = make([]*logMessage, 0) + logMessagesByName = make(map[string]*logMessage) +) + +type logMessage struct { + time time.Time + name string + level logger.Level + msg string +} + +func stdLogMsg(level logger.Level, name string, msg string) { + stdlog.Printf("[ %s ] %s: %s", + level.CapitalString(), + name, + msg, + ) +} + +func storeLogMsg(level logger.Level, name string, message string) { + mu.Lock() + defer mu.Unlock() + + logMessages = append(logMessages, &logMessage{ + time: time.Now(), + name: name, + level: level, + msg: message, }) - if statusMessage, exists := statusMessages[prefix]; !exists { - statusMessages[prefix] = &StatusMessage{ - Source: prefix, - LogLevel: logLevel, - Message: message, - Time: time.Now(), + if statusMessage, exists := logMessagesByName[name]; !exists { + logMessagesByName[name] = &logMessage{ + time: time.Now(), + name: name, + level: level, + msg: message, } } else { - statusMessage.LogLevel = logLevel - statusMessage.Message = message - statusMessage.Time = time.Now() + statusMessage.time = time.Now() + statusMessage.level = level + statusMessage.msg = message } } diff --git a/plugins/statusscreen/plugin.go b/plugins/statusscreen/plugin.go new file mode 100644 index 00000000..544e1900 --- /dev/null +++ b/plugins/statusscreen/plugin.go @@ -0,0 +1,81 @@ +package statusscreen + +import ( + "time" + + "github.com/iotaledger/hive.go/daemon" + "github.com/iotaledger/hive.go/events" + "github.com/iotaledger/hive.go/logger" + "github.com/iotaledger/hive.go/node" +) + +const ( + name = "Statusscreen" + repaintInterval = 1 * time.Second +) + +var PLUGIN = node.NewPlugin(name, node.Enabled, configure, run) + +var ( + stdLogMsgClosure = events.NewClosure(stdLogMsg) + storeLogMsgClosure = events.NewClosure(storeLogMsg) +) + +func init() { + // use standard go logger by default + logger.Events.AnyMsg.Attach(stdLogMsgClosure) +} + +func configure(*node.Plugin) { + if !isTerminal() { + return + } + + // store any log message for display + logger.Events.AnyMsg.Attach(storeLogMsgClosure) + + log = logger.NewLogger(name) + configureTview() +} + +func run(*node.Plugin) { + if !isTerminal() { + return + } + + stopped := make(chan struct{}) + err := daemon.BackgroundWorker(name+" Refresher", func(shutdown <-chan struct{}) { + for { + select { + case <-time.After(repaintInterval): + app.QueueUpdateDraw(func() {}) + case <-shutdown: + logger.Events.AnyMsg.Detach(storeLogMsgClosure) + app.Stop() + return + case <-stopped: + return + } + } + }) + if err != nil { + log.Errorf("Failed to start as daemon: %s", err) + return + } + + err = daemon.BackgroundWorker(name+" App", func(<-chan struct{}) { + defer close(stopped) + + // switch logging to status screen + logger.Events.AnyMsg.Detach(stdLogMsgClosure) + defer logger.Events.AnyMsg.Attach(stdLogMsgClosure) + + if err := app.SetRoot(frame, true).SetFocus(frame).Run(); err != nil { + log.Errorf("Error running application: %s", err) + } + }) + if err != nil { + log.Errorf("Failed to start as daemon: %s", err) + close(stopped) + } +} diff --git a/plugins/statusscreen/status_message.go b/plugins/statusscreen/status_message.go deleted file mode 100644 index 2ec23aff..00000000 --- a/plugins/statusscreen/status_message.go +++ /dev/null @@ -1,14 +0,0 @@ -package statusscreen - -import ( - "time" - - "github.com/iotaledger/hive.go/logger" -) - -type StatusMessage struct { - Source string - LogLevel logger.Level - Message string - Time time.Time -} diff --git a/plugins/statusscreen/statusscreen.go b/plugins/statusscreen/statusscreen.go index 0d51af1e..40acb01b 100644 --- a/plugins/statusscreen/statusscreen.go +++ b/plugins/statusscreen/statusscreen.go @@ -2,61 +2,21 @@ package statusscreen import ( "os" - "sync" - "time" "github.com/gdamore/tcell" "github.com/iotaledger/hive.go/daemon" - "github.com/iotaledger/hive.go/events" "github.com/iotaledger/hive.go/logger" - "github.com/iotaledger/hive.go/node" "github.com/rivo/tview" "golang.org/x/crypto/ssh/terminal" ) -var statusMessages = make(map[string]*StatusMessage) -var messageLog = make([]*StatusMessage, 0) -var mutex sync.RWMutex - -var app *tview.Application - -func configure(plugin *node.Plugin) { - if !terminal.IsTerminal(int(os.Stdin.Fd())) { - return - } - - // store any log message for display - anyLogMsgClosure := events.NewClosure(func(logLevel logger.Level, prefix string, msg string) { - storeStatusMessage(logLevel, prefix, msg) - }) - logger.Events.AnyMsg.Attach(anyLogMsgClosure) - - daemon.BackgroundWorker("UI-Detach", func(shutdownSignal <-chan struct{}) { - <-shutdownSignal - logger.Events.AnyMsg.Detach(anyLogMsgClosure) - if app != nil { - app.Stop() - } - }, 1) -} - -func run(plugin *node.Plugin) { - if !terminal.IsTerminal(int(os.Stdin.Fd())) { - return - } - - newPrimitive := func(text string) *tview.TextView { - textView := tview.NewTextView() - - textView. - SetTextAlign(tview.AlignLeft). - SetText(" " + text) - - return textView - } - - app = tview.NewApplication() +var ( + log *logger.Logger + app *tview.Application + frame *tview.Frame +) +func configureTview() { headerBar := NewUIHeaderBar() content := tview.NewGrid() @@ -78,30 +38,28 @@ func run(plugin *node.Plugin) { AddItem(content, 1, 0, 1, 1, 0, 0, false). AddItem(footer, 2, 0, 1, 1, 0, 0, false) - frame := tview.NewFrame(grid). + frame = tview.NewFrame(grid). SetBorders(1, 1, 0, 0, 2, 2) frame.SetBackgroundColor(tcell.ColorDarkGray) + app = tview.NewApplication() app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + // end the daemon on ctrl+c if event.Key() == tcell.KeyCtrlC || event.Key() == tcell.KeyESC { daemon.Shutdown() - return nil } - return event }) app.SetBeforeDrawFunc(func(screen tcell.Screen) bool { - mutex.RLock() - defer mutex.RUnlock() headerBar.Update() rows := make([]int, 2) rows[0] = 1 rows[1] = 1 _, _, _, height := content.GetRect() - for i := 0; i < len(messageLog) && i < height-2; i++ { + for i := 0; i < len(logMessages) && i < height-2; i++ { rows = append(rows, 1) } @@ -112,12 +70,12 @@ func run(plugin *node.Plugin) { blankLine.SetBackgroundColor(tcell.ColorWhite) content.AddItem(blankLine, 0, 0, 1, 1, 0, 0, false) - logStart := len(messageLog) - (len(rows) - 2) + logStart := len(logMessages) - (len(rows) - 2) if logStart < 0 { logStart = 0 } - for i, message := range messageLog[logStart:] { + for i, message := range logMessages[logStart:] { if i < height-2 { content.AddItem(NewUILogEntry(*message).Primitive, i+1, 0, 1, 1, 0, 0, false) } @@ -129,23 +87,15 @@ func run(plugin *node.Plugin) { return false }) +} - daemon.BackgroundWorker("Statusscreen Refresher", func(shutdownSignal <-chan struct{}) { - for { - select { - case <-shutdownSignal: - return - case <-time.After(1 * time.Second): - app.QueueUpdateDraw(func() {}) - } - } - }) +func newPrimitive(text string) *tview.TextView { + textView := tview.NewTextView() + textView.SetTextAlign(tview.AlignLeft).SetText(" " + text) - daemon.BackgroundWorker("Statusscreen App", func(shutdownSignal <-chan struct{}) { - if err := app.SetRoot(frame, true).SetFocus(frame).Run(); err != nil { - panic(err) - } - }) + return textView } -var PLUGIN = node.NewPlugin("Status Screen", node.Enabled, configure, run) +func isTerminal() bool { + return terminal.IsTerminal(int(os.Stdin.Fd())) +} diff --git a/plugins/statusscreen/ui_log.go b/plugins/statusscreen/ui_log.go deleted file mode 100644 index 6dae6566..00000000 --- a/plugins/statusscreen/ui_log.go +++ /dev/null @@ -1,15 +0,0 @@ -package statusscreen - -import "github.com/rivo/tview" - -type UILog struct { - Primitive *tview.Grid -} - -func NewUILog() *UILog { - uiLog := &UILog{ - Primitive: tview.NewGrid(), - } - - return uiLog -} diff --git a/plugins/statusscreen/ui_log_entry.go b/plugins/statusscreen/ui_log_entry.go index 4134636d..57cbc6e7 100644 --- a/plugins/statusscreen/ui_log_entry.go +++ b/plugins/statusscreen/ui_log_entry.go @@ -15,7 +15,7 @@ type UILogEntry struct { LogLevelContainer *tview.TextView } -func NewUILogEntry(message StatusMessage) *UILogEntry { +func NewUILogEntry(message logMessage) *UILogEntry { logEntry := &UILogEntry{ Primitive: tview.NewGrid(), TimeContainer: tview.NewTextView(), @@ -36,7 +36,7 @@ func NewUILogEntry(message StatusMessage) *UILogEntry { logEntry.LogLevelContainer.SetDynamicColors(true) textColor := "black::d" - switch message.LogLevel { + switch message.level { case logger.LevelInfo: fmt.Fprintf(logEntry.LogLevelContainer, " [black::d][ [blue::d]INFO [black::d]]") case logger.LevelWarn: @@ -57,11 +57,11 @@ func NewUILogEntry(message StatusMessage) *UILogEntry { textColor = "black::b" } - fmt.Fprintf(logEntry.TimeContainer, " [black::b]"+message.Time.Format("15:04:05")) - if message.Source == "Node" { - fmt.Fprintf(logEntry.MessageContainer, "["+textColor+"]"+message.Message) + fmt.Fprintf(logEntry.TimeContainer, " [black::b]"+message.time.Format("15:04:05")) + if message.name == "Node" { + fmt.Fprintf(logEntry.MessageContainer, "["+textColor+"]"+message.msg) } else { - fmt.Fprintf(logEntry.MessageContainer, "["+textColor+"]"+message.Source+": "+message.Message) + fmt.Fprintf(logEntry.MessageContainer, "["+textColor+"]"+message.name+": "+message.msg) } logEntry.Primitive. -- GitLab