Skip to content
Snippets Groups Projects
Unverified Commit f5015a38 authored by Luca Moser's avatar Luca Moser Committed by GitHub
Browse files

Removes status screen plugin (#228)

* removes status screen plugin

* removes statusscreen entry from docker config, disable logger events per default
parent f221a46e
No related branches found
No related tags found
No related merge requests found
......@@ -44,9 +44,10 @@
"disableStacktrace": false,
"encoding": "console",
"outputPaths": [
"stdout",
"goshimmer.log"
],
"disableEvents": false
"disableEvents": true
},
"network": {
"bindAddress": "0.0.0.0",
......
......@@ -28,9 +28,7 @@
"DisableEvents": true
},
"node": {
"disablePlugins": [
"statusscreen"
],
"disablePlugins": [],
"enablePlugins": []
}
}
......@@ -13,8 +13,6 @@ import (
"github.com/iotaledger/goshimmer/plugins/graph"
"github.com/iotaledger/goshimmer/plugins/metrics"
"github.com/iotaledger/goshimmer/plugins/spa"
"github.com/iotaledger/goshimmer/plugins/statusscreen"
statusscreen_tps "github.com/iotaledger/goshimmer/plugins/statusscreen-tps"
"github.com/iotaledger/goshimmer/plugins/tangle"
"github.com/iotaledger/goshimmer/plugins/tipselection"
"github.com/iotaledger/goshimmer/plugins/webapi"
......@@ -46,9 +44,6 @@ func main() {
tipselection.PLUGIN,
metrics.PLUGIN,
statusscreen.PLUGIN,
statusscreen_tps.PLUGIN,
webapi.PLUGIN,
webapi_auth.PLUGIN,
webapi_gtta.PLUGIN,
......
package statusscreen_tps
import (
"strconv"
"sync/atomic"
"time"
"github.com/iotaledger/goshimmer/packages/gossip"
"github.com/iotaledger/goshimmer/packages/model/value_transaction"
"github.com/iotaledger/goshimmer/packages/shutdown"
"github.com/iotaledger/goshimmer/plugins/statusscreen"
"github.com/iotaledger/goshimmer/plugins/tangle"
"github.com/iotaledger/hive.go/daemon"
"github.com/iotaledger/hive.go/events"
"github.com/iotaledger/hive.go/node"
)
var receivedTpsCounter uint64
var solidTpsCounter uint64
var receivedTps uint64
var solidTps uint64
var PLUGIN = node.NewPlugin("Statusscreen TPS", node.Enabled, func(plugin *node.Plugin) {
gossip.Events.TransactionReceived.Attach(events.NewClosure(func(_ *gossip.TransactionReceivedEvent) {
atomic.AddUint64(&receivedTpsCounter, 1)
}))
tangle.Events.TransactionSolid.Attach(events.NewClosure(func(_ *value_transaction.ValueTransaction) {
atomic.AddUint64(&solidTpsCounter, 1)
}))
statusscreen.AddHeaderInfo(func() (s string, s2 string) {
return "TPS", strconv.FormatUint(atomic.LoadUint64(&receivedTps), 10) + " received / " + strconv.FormatUint(atomic.LoadUint64(&solidTps), 10) + " new"
})
}, func(plugin *node.Plugin) {
daemon.BackgroundWorker("Statusscreen TPS Tracker", func(shutdownSignal <-chan struct{}) {
ticker := time.NewTicker(time.Second)
for {
select {
case <-shutdownSignal:
return
case <-ticker.C:
atomic.StoreUint64(&receivedTps, atomic.LoadUint64(&receivedTpsCounter))
atomic.StoreUint64(&solidTps, atomic.LoadUint64(&solidTpsCounter))
atomic.StoreUint64(&receivedTpsCounter, 0)
atomic.StoreUint64(&solidTpsCounter, 0)
}
}
}, shutdown.ShutdownPriorityStatusScreen)
})
package statusscreen
import (
stdlog "log"
"sync"
"time"
"github.com/iotaledger/hive.go/logger"
)
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 := logMessagesByName[name]; !exists {
logMessagesByName[name] = &logMessage{
time: time.Now(),
name: name,
level: level,
msg: message,
}
} else {
statusMessage.time = time.Now()
statusMessage.level = level
statusMessage.msg = message
}
}
package statusscreen
import (
"time"
"github.com/iotaledger/goshimmer/packages/shutdown"
"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{})
if 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
}
}
}, shutdown.ShutdownPriorityStatusScreen); err != nil {
log.Errorf("Failed to start as daemon: %s", err)
return
}
if 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)
}
}, shutdown.ShutdownPriorityStatusScreen); err != nil {
log.Errorf("Failed to start as daemon: %s", err)
close(stopped)
}
}
package statusscreen
import (
"os"
"github.com/gdamore/tcell"
"github.com/iotaledger/hive.go/daemon"
"github.com/iotaledger/hive.go/logger"
"github.com/rivo/tview"
"golang.org/x/crypto/ssh/terminal"
)
var (
log *logger.Logger
app *tview.Application
frame *tview.Frame
)
func configureTview() {
headerBar := NewUIHeaderBar()
content := tview.NewGrid()
content.SetBackgroundColor(tcell.ColorWhite)
content.SetColumns(0)
content.SetBorders(false)
content.SetOffset(0, 0)
content.SetGap(0, 0)
footer := newPrimitive("")
footer.SetBackgroundColor(tcell.ColorDarkMagenta)
footer.SetTextColor(tcell.ColorWhite)
grid := tview.NewGrid().
SetRows(10, 0, 1).
SetColumns(0).
SetBorders(false).
AddItem(headerBar.Primitive, 0, 0, 1, 1, 0, 0, false).
AddItem(content, 1, 0, 1, 1, 0, 0, false).
AddItem(footer, 2, 0, 1, 1, 0, 0, false)
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 {
headerBar.Update()
rows := make([]int, 2)
rows[0] = 1
rows[1] = 1
_, _, _, height := content.GetRect()
for i := 0; i < len(logMessages) && i < height-2; i++ {
rows = append(rows, 1)
}
content.Clear()
content.SetRows(rows...)
blankLine := newPrimitive("")
blankLine.SetBackgroundColor(tcell.ColorWhite)
content.AddItem(blankLine, 0, 0, 1, 1, 0, 0, false)
logStart := len(logMessages) - (len(rows) - 2)
if logStart < 0 {
logStart = 0
}
for i, message := range logMessages[logStart:] {
if i < height-2 {
content.AddItem(NewUILogEntry(*message).Primitive, i+1, 0, 1, 1, 0, 0, false)
}
}
blankLine = newPrimitive("")
blankLine.SetBackgroundColor(tcell.ColorWhite)
content.AddItem(blankLine, height-1, 0, 1, 1, 0, 0, false)
return false
})
}
func newPrimitive(text string) *tview.TextView {
textView := tview.NewTextView()
textView.SetTextAlign(tview.AlignLeft).SetText(" " + text)
return textView
}
func isTerminal() bool {
return terminal.IsTerminal(int(os.Stdin.Fd()))
}
package statusscreen
import (
"fmt"
"math"
"strconv"
"time"
"github.com/gdamore/tcell"
"github.com/iotaledger/goshimmer/plugins/autopeering"
"github.com/iotaledger/goshimmer/plugins/autopeering/local"
"github.com/iotaledger/goshimmer/plugins/cli"
"github.com/rivo/tview"
)
var start = time.Now()
var headerInfos = make([]func() (string, string), 0)
func AddHeaderInfo(generator func() (string, string)) {
headerInfos = append(headerInfos, generator)
}
type UIHeaderBar struct {
Primitive *tview.Grid
LogoContainer *tview.TextView
InfoContainer *tview.TextView
}
func NewUIHeaderBar() *UIHeaderBar {
headerBar := &UIHeaderBar{
Primitive: tview.NewGrid(),
LogoContainer: tview.NewTextView(),
InfoContainer: tview.NewTextView(),
}
headerBar.LogoContainer.
SetTextAlign(tview.AlignLeft).
SetTextColor(tcell.ColorWhite).
SetDynamicColors(true).
SetBackgroundColor(tcell.ColorDarkMagenta)
headerBar.InfoContainer.
SetTextAlign(tview.AlignRight).
SetTextColor(tcell.ColorWhite).
SetDynamicColors(true).
SetBackgroundColor(tcell.ColorDarkMagenta)
headerBar.Primitive.
SetColumns(20, 0).
SetRows(0).
SetBorders(false).
AddItem(headerBar.LogoContainer, 0, 0, 1, 1, 0, 0, false).
AddItem(headerBar.InfoContainer, 0, 1, 1, 1, 0, 0, false)
headerBar.printLogo()
headerBar.Update()
return headerBar
}
func (headerBar *UIHeaderBar) Update() {
duration := time.Since(start)
headerBar.InfoContainer.Clear()
fmt.Fprintln(headerBar.InfoContainer)
fmt.Fprintln(headerBar.InfoContainer, "[::d]COO-LESS IOTA PROTOTYPE - [::b]Status: [green::b]SYNCED ")
for i := 0; i < 3-len(headerInfos); i++ {
fmt.Fprintln(headerBar.InfoContainer)
}
for _, infoGenerator := range headerInfos {
fieldName, fieldValue := infoGenerator()
fmt.Fprintf(headerBar.InfoContainer, "[::b]%v: [::d]%40v ", fieldName, fieldValue)
fmt.Fprintln(headerBar.InfoContainer)
}
outgoing := "0"
incoming := "0"
neighbors := "0"
total := "0"
myID := "-"
if autopeering.Selection != nil {
outgoing = strconv.Itoa(len(autopeering.Selection.GetOutgoingNeighbors()))
incoming = strconv.Itoa(len(autopeering.Selection.GetIncomingNeighbors()))
neighbors = strconv.Itoa(len(autopeering.Selection.GetNeighbors()))
}
if autopeering.Discovery != nil {
total = strconv.Itoa(len(autopeering.Discovery.GetVerifiedPeers()))
}
if local.GetInstance() != nil {
myID = local.GetInstance().ID().String()
}
fmt.Fprintf(headerBar.InfoContainer, "[::b]Node ID: [::d]%40v ", myID)
fmt.Fprintln(headerBar.InfoContainer)
fmt.Fprintf(headerBar.InfoContainer, "[::b]Neighbors: [::d]%40v ", outgoing+" chosen / "+incoming+" accepted / "+neighbors+" total")
fmt.Fprintln(headerBar.InfoContainer)
fmt.Fprintf(headerBar.InfoContainer, "[::b]Known Peers: [::d]%40v ", total+" total")
fmt.Fprintln(headerBar.InfoContainer)
fmt.Fprintf(headerBar.InfoContainer, "[::b]Uptime: [::d]")
padded := false
if int(duration.Seconds())/(60*60*24) > 0 {
days := int(duration.Hours()) / 24
numberLength := int(math.Log10(float64(days))) + 1
padLength := 31 - numberLength
fmt.Fprintf(headerBar.InfoContainer, "%*v", padLength, "")
padded = true
// d
fmt.Fprintf(headerBar.InfoContainer, "%02dd ", days)
}
if int(duration.Seconds())/(60*60) > 0 {
if !padded {
fmt.Fprintf(headerBar.InfoContainer, "%29v", "")
padded = true
}
fmt.Fprintf(headerBar.InfoContainer, "%02dh ", int(duration.Hours())%24)
}
if int(duration.Seconds())/60 > 0 {
if !padded {
fmt.Fprintf(headerBar.InfoContainer, "%33v", "")
padded = true
}
fmt.Fprintf(headerBar.InfoContainer, "%02dm ", int(duration.Minutes())%60)
}
if !padded {
fmt.Fprintf(headerBar.InfoContainer, "%37v", "")
}
fmt.Fprintf(headerBar.InfoContainer, "%02ds ", int(duration.Seconds())%60)
}
func (headerBar *UIHeaderBar) printLogo() {
fmt.Fprintln(headerBar.LogoContainer, "")
fmt.Fprintln(headerBar.LogoContainer, " GOSHIMMER", cli.AppVersion)
fmt.Fprintln(headerBar.LogoContainer, " ┌──────┬──────┐")
fmt.Fprintln(headerBar.LogoContainer, " ───┐ │ ┌───")
fmt.Fprintln(headerBar.LogoContainer, " ┐ │ │ │ ┌")
fmt.Fprintln(headerBar.LogoContainer, " │ └ │ ┘ │")
fmt.Fprintln(headerBar.LogoContainer, " └ ┌ │ ┐ ┘")
fmt.Fprintln(headerBar.LogoContainer, " │ │ │")
fmt.Fprintln(headerBar.LogoContainer, " ┴")
}
package statusscreen
import (
"fmt"
"github.com/gdamore/tcell"
"github.com/iotaledger/hive.go/logger"
"github.com/rivo/tview"
)
type UILogEntry struct {
Primitive *tview.Grid
TimeContainer *tview.TextView
MessageContainer *tview.TextView
LogLevelContainer *tview.TextView
}
func NewUILogEntry(message logMessage) *UILogEntry {
logEntry := &UILogEntry{
Primitive: tview.NewGrid(),
TimeContainer: tview.NewTextView(),
MessageContainer: tview.NewTextView(),
LogLevelContainer: tview.NewTextView(),
}
logEntry.TimeContainer.SetBackgroundColor(tcell.ColorWhite)
logEntry.TimeContainer.SetTextColor(tcell.ColorBlack)
logEntry.TimeContainer.SetDynamicColors(true)
logEntry.MessageContainer.SetBackgroundColor(tcell.ColorWhite)
logEntry.MessageContainer.SetTextColor(tcell.ColorBlack)
logEntry.MessageContainer.SetDynamicColors(true)
logEntry.LogLevelContainer.SetBackgroundColor(tcell.ColorWhite)
logEntry.LogLevelContainer.SetTextColor(tcell.ColorBlack)
logEntry.LogLevelContainer.SetDynamicColors(true)
textColor := "black::d"
switch message.level {
case logger.LevelInfo:
fmt.Fprintf(logEntry.LogLevelContainer, " [black::d][ [blue::d]INFO [black::d]]")
case logger.LevelWarn:
fmt.Fprintf(logEntry.LogLevelContainer, " [black::d][ [yellow::d]WARN [black::d]]")
textColor = "yellow::d"
case logger.LevelError:
fallthrough
case logger.LevelPanic:
fallthrough
case logger.LevelFatal:
fmt.Fprintf(logEntry.LogLevelContainer, " [black::d][ [red::d]FAIL [black::d]]")
textColor = "red::d"
case logger.LevelDebug:
fmt.Fprintf(logEntry.LogLevelContainer, " [black::d][ [black::b]NOTE [black::d]]")
textColor = "black::b"
}
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.name+": "+message.msg)
}
logEntry.Primitive.
SetColumns(11, 0, 11).
SetRows(1).
SetBorders(false).
AddItem(logEntry.TimeContainer, 0, 0, 1, 1, 0, 0, false).
AddItem(logEntry.MessageContainer, 0, 1, 1, 1, 0, 0, false).
AddItem(logEntry.LogLevelContainer, 0, 2, 1, 1, 0, 0, false)
return logEntry
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment