diff options
| author | Paul Buetow <paul@buetow.org> | 2021-09-06 09:22:21 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2021-09-06 09:22:21 +0300 |
| commit | 2c1c70313bb03cf2b2d7e7afadb07a48ff6bb690 (patch) | |
| tree | 2ea3402bc6dd2d3e3ce0754eb3d5c90305e87c2e | |
| parent | c895b3c8293ddbf46d66278061d7e0127adc57f7 (diff) | |
REMOTE and CLIENT colors are brushed correctly too now
| -rw-r--r-- | TODO.md | 7 | ||||
| -rw-r--r-- | docker/Makefile | 4 | ||||
| -rw-r--r-- | internal/clients/stats.go | 14 | ||||
| -rw-r--r-- | internal/color/brush/brush.go | 231 | ||||
| -rw-r--r-- | internal/config/client.go | 229 |
5 files changed, 305 insertions, 180 deletions
@@ -5,6 +5,11 @@ This is a loose list of what to do. Maybe for the next releae or maybe for a lat [x] Finalize default color schema [x] Use a buffered string builder for brushing the colors in the client. +[x] Extended color table output (print whole paragraphs in colors) +[x] Have different color conf sections (by REMOTE, CLIENT, SERVER) +[x] Paint ^CLIENT messages (e.g. use yellow backgrounds here) +[x] Paint ^SERVER messages (e.g. use cyan backgrounds here) +[ ] Fix JSONSchema for the colors [ ] Implement Benchmark cat-ing a file and compare to prev version. [ ] Client 4.x should print a warning when trying to connect to a 3.x server. -[ ] Fix paintClientStats +[ ] Update docs for color configuration diff --git a/docker/Makefile b/docker/Makefile index 5013c28..a4ffa19 100644 --- a/docker/Makefile +++ b/docker/Makefile @@ -9,8 +9,8 @@ spinup: spindown: ./spindown.sh 10 dtail: - ../dtail --servers serverlist.txt --files '/var/log/dserver/*' --trustAllHosts + ../dtail --servers serverlist.txt --files '/var/log/dserver/*,/does/not/exist' --trustAllHosts --debug dcat: - ../dcat --servers serverlist.txt --files '/etc/passwd' --trustAllHosts + ../dcat --servers serverlist.txt --files '/etc/passwd' --trustAllHosts --debug spinup1: docker run -p 2222:2222 dserver:develop diff --git a/internal/clients/stats.go b/internal/clients/stats.go index d8163d4..3f76e0f 100644 --- a/internal/clients/stats.go +++ b/internal/clients/stats.go @@ -8,6 +8,7 @@ import ( "sync" "time" + "github.com/mimecast/dtail/internal/color" "github.com/mimecast/dtail/internal/config" "github.com/mimecast/dtail/internal/io/logger" ) @@ -54,7 +55,6 @@ func (s *stats) Start(ctx context.Context, throttleCh <-chan struct{}, statsCh < throttle := len(throttleCh) newConnections := connected - connectedLast - if (connected == connectedLast || quiet) && !force { continue } @@ -77,7 +77,15 @@ func (s *stats) Start(ctx context.Context, throttleCh <-chan struct{}, statsCh < func (s *stats) printStatsDueInterrupt(messages []string) { logger.Pause() - for _, message := range messages { + for i, message := range messages { + if i > 0 && config.Client.TermColorsEnable { + fmt.Println(color.PaintStrWithAttr(message, + config.Client.TermColors.Client.TextFg, + config.Client.TermColors.Client.TextBg, + config.Client.TermColors.Client.TextAttr, + )) + continue + } fmt.Println(fmt.Sprintf(" %s", message)) } time.Sleep(time.Second * time.Duration(config.InterruptTimeoutS)) @@ -99,7 +107,6 @@ func (s *stats) statsLine(connected, newConnections int, throttle int) string { func (s *stats) numConnected() int { s.mutex.Lock() defer s.mutex.Unlock() - return s.connected } @@ -107,6 +114,5 @@ func percentOf(total float64, value float64) float64 { if total == 0 || total == value { return 100 } - return value / (total / 100.0) } diff --git a/internal/color/brush/brush.go b/internal/color/brush/brush.go index 415028a..785a0d0 100644 --- a/internal/color/brush/brush.go +++ b/internal/color/brush/brush.go @@ -8,105 +8,165 @@ import ( "github.com/mimecast/dtail/internal/protocol" ) -// Add some color to log lines received from remote servers. +func paintSeverity(sb *strings.Builder, text string) bool { + switch { + case strings.HasPrefix(text, "WARN"): + color.PaintWithAttr(sb, text, + config.Client.TermColors.Common.SeverityWarnFg, + config.Client.TermColors.Common.SeverityWarnBg, + config.Client.TermColors.Common.SeverityWarnAttr) + + case strings.HasPrefix(text, "ERROR"): + color.PaintWithAttr(sb, text, + config.Client.TermColors.Common.SeverityErrorFg, + config.Client.TermColors.Common.SeverityErrorBg, + config.Client.TermColors.Common.SeverityErrorAttr) + + case strings.HasPrefix(text, "FATAL"): + color.PaintWithAttr(sb, text, + config.Client.TermColors.Common.SeverityFatalFg, + config.Client.TermColors.Common.SeverityFatalBg, + config.Client.TermColors.Common.SeverityFatalAttr) + + default: + return false + } + + return true +} + func paintRemote(sb *strings.Builder, line string) { splitted := strings.SplitN(line, protocol.FieldDelimiter, 6) color.PaintWithAttr(sb, splitted[0], - config.Client.TermColors.RemoteStrFg, - config.Client.TermColors.RemoteStrBg, - config.Client.TermColors.RemoteStrAttr) + config.Client.TermColors.Remote.RemoteFg, + config.Client.TermColors.Remote.RemoteBg, + config.Client.TermColors.Remote.RemoteAttr) color.PaintWithAttr(sb, protocol.FieldDelimiter, - config.Client.TermColors.DelimiterFg, - config.Client.TermColors.DelimiterBg, - config.Client.TermColors.DelimiterAttr) + config.Client.TermColors.Remote.DelimiterFg, + config.Client.TermColors.Remote.DelimiterBg, + config.Client.TermColors.Remote.DelimiterAttr) color.PaintWithAttr(sb, splitted[1], - config.Client.TermColors.RemoteServerFg, - config.Client.TermColors.RemoteServerBg, - config.Client.TermColors.RemoteServerAttr) + config.Client.TermColors.Remote.HostnameFg, + config.Client.TermColors.Remote.HostnameBg, + config.Client.TermColors.Remote.HostnameAttr) color.PaintWithAttr(sb, protocol.FieldDelimiter, - config.Client.TermColors.DelimiterFg, - config.Client.TermColors.DelimiterBg, - config.Client.TermColors.DelimiterAttr) + config.Client.TermColors.Remote.DelimiterFg, + config.Client.TermColors.Remote.DelimiterBg, + config.Client.TermColors.Remote.DelimiterAttr) if splitted[2] == "100" { color.PaintWithAttr(sb, splitted[2], - config.Client.TermColors.RemoteStatsOkFg, - config.Client.TermColors.RemoteStatsOkBg, - config.Client.TermColors.RemoteStatsOkAttr) + config.Client.TermColors.Remote.StatsOkFg, + config.Client.TermColors.Remote.StatsOkBg, + config.Client.TermColors.Remote.StatsOkAttr) } else { color.PaintWithAttr(sb, splitted[2], - config.Client.TermColors.RemoteStatsWarnFg, - config.Client.TermColors.RemoteStatsWarnBg, - config.Client.TermColors.RemoteStatsWarnAttr) + config.Client.TermColors.Remote.StatsWarnFg, + config.Client.TermColors.Remote.StatsWarnBg, + config.Client.TermColors.Remote.StatsWarnAttr) } color.PaintWithAttr(sb, protocol.FieldDelimiter, - config.Client.TermColors.DelimiterFg, - config.Client.TermColors.DelimiterBg, - config.Client.TermColors.DelimiterAttr) + config.Client.TermColors.Remote.DelimiterFg, + config.Client.TermColors.Remote.DelimiterBg, + config.Client.TermColors.Remote.DelimiterAttr) color.PaintWithAttr(sb, splitted[3], - config.Client.TermColors.RemoteCountFg, - config.Client.TermColors.RemoteCountBg, - config.Client.TermColors.RemoteCountAttr) + config.Client.TermColors.Remote.CountFg, + config.Client.TermColors.Remote.CountBg, + config.Client.TermColors.Remote.CountAttr) color.PaintWithAttr(sb, protocol.FieldDelimiter, - config.Client.TermColors.DelimiterFg, - config.Client.TermColors.DelimiterBg, - config.Client.TermColors.DelimiterAttr) + config.Client.TermColors.Remote.DelimiterFg, + config.Client.TermColors.Remote.DelimiterBg, + config.Client.TermColors.Remote.DelimiterAttr) color.PaintWithAttr(sb, splitted[4], - config.Client.TermColors.RemoteIdFg, - config.Client.TermColors.RemoteIdBg, - config.Client.TermColors.RemoteIdAttr) + config.Client.TermColors.Remote.IdFg, + config.Client.TermColors.Remote.IdBg, + config.Client.TermColors.Remote.IdAttr) color.PaintWithAttr(sb, protocol.FieldDelimiter, - config.Client.TermColors.DelimiterFg, - config.Client.TermColors.DelimiterBg, - config.Client.TermColors.DelimiterAttr) + config.Client.TermColors.Remote.DelimiterFg, + config.Client.TermColors.Remote.DelimiterBg, + config.Client.TermColors.Remote.DelimiterAttr) - log := splitted[5] + if paintSeverity(sb, splitted[5]) { + return + } + color.PaintWithAttr(sb, splitted[5], + config.Client.TermColors.Remote.TextFg, + config.Client.TermColors.Remote.TextBg, + config.Client.TermColors.Remote.TextAttr) +} - switch { - case strings.HasPrefix(log, "WARN"): - color.PaintWithAttr(sb, log, - config.Client.TermColors.RemoteWarnFg, - config.Client.TermColors.RemoteWarnBg, - config.Client.TermColors.RemoteWarnAttr) - - case strings.HasPrefix(log, "ERROR"): - color.PaintWithAttr(sb, log, - config.Client.TermColors.RemoteErrorFg, - config.Client.TermColors.RemoteErrorBg, - config.Client.TermColors.RemoteErrorAttr) - - case strings.HasPrefix(log, "FATAL"): - color.PaintWithAttr(sb, log, - config.Client.TermColors.RemoteFatalFg, - config.Client.TermColors.RemoteFatalBg, - config.Client.TermColors.RemoteFatalAttr) - - case strings.HasPrefix(log, "DEBUG"): - color.PaintWithAttr(sb, log, - config.Client.TermColors.RemoteDebugFg, - config.Client.TermColors.RemoteDebugBg, - config.Client.TermColors.RemoteDebugAttr) - - case strings.HasPrefix(log, "TRACE"): - color.PaintWithAttr(sb, log, - config.Client.TermColors.RemoteTraceFg, - config.Client.TermColors.RemoteTraceBg, - config.Client.TermColors.RemoteTraceAttr) +func paintClient(sb *strings.Builder, line string) { + splitted := strings.SplitN(line, protocol.FieldDelimiter, 3) - default: - color.PaintWithAttr(sb, log, - config.Client.TermColors.RemoteTextFg, - config.Client.TermColors.RemoteTextBg, - config.Client.TermColors.RemoteTextAttr) + color.PaintWithAttr(sb, splitted[0], + config.Client.TermColors.Client.ClientFg, + config.Client.TermColors.Client.ClientBg, + config.Client.TermColors.Client.ClientAttr) + + color.PaintWithAttr(sb, protocol.FieldDelimiter, + config.Client.TermColors.Client.DelimiterFg, + config.Client.TermColors.Client.DelimiterBg, + config.Client.TermColors.Client.DelimiterAttr) + + color.PaintWithAttr(sb, splitted[1], + config.Client.TermColors.Client.HostnameFg, + config.Client.TermColors.Client.HostnameBg, + config.Client.TermColors.Client.HostnameAttr) + + color.PaintWithAttr(sb, protocol.FieldDelimiter, + config.Client.TermColors.Client.DelimiterFg, + config.Client.TermColors.Client.DelimiterBg, + config.Client.TermColors.Client.DelimiterAttr) + + if paintSeverity(sb, splitted[2]) { + return } + + color.PaintWithAttr(sb, splitted[2], + config.Client.TermColors.Client.TextFg, + config.Client.TermColors.Client.TextBg, + config.Client.TermColors.Client.TextAttr) +} + +func paintServer(sb *strings.Builder, line string) { + splitted := strings.SplitN(line, protocol.FieldDelimiter, 3) + + color.PaintWithAttr(sb, splitted[0], + config.Client.TermColors.Server.ServerFg, + config.Client.TermColors.Server.ServerBg, + config.Client.TermColors.Server.ServerAttr) + + color.PaintWithAttr(sb, protocol.FieldDelimiter, + config.Client.TermColors.Server.DelimiterFg, + config.Client.TermColors.Server.DelimiterBg, + config.Client.TermColors.Server.DelimiterAttr) + + color.PaintWithAttr(sb, splitted[1], + config.Client.TermColors.Server.HostnameFg, + config.Client.TermColors.Server.HostnameBg, + config.Client.TermColors.Server.HostnameAttr) + + color.PaintWithAttr(sb, protocol.FieldDelimiter, + config.Client.TermColors.Server.DelimiterFg, + config.Client.TermColors.Server.DelimiterBg, + config.Client.TermColors.Server.DelimiterAttr) + + if paintSeverity(sb, splitted[2]) { + return + } + + color.PaintWithAttr(sb, splitted[2], + config.Client.TermColors.Server.TextFg, + config.Client.TermColors.Server.TextBg, + config.Client.TermColors.Server.TextAttr) } // Colorfy a given line based on the line's content. @@ -117,18 +177,25 @@ func Colorfy(line string) string { case strings.HasPrefix(line, "REMOTE"): paintRemote(&sb, line) - case strings.Contains(line, "ERROR"): - color.PaintWithAttr(&sb, line, - config.Client.TermColors.ClientErrorFg, - config.Client.TermColors.ClientErrorBg, - config.Client.TermColors.ClientErrorAttr) - - case strings.Contains(line, "WARN"): - color.PaintWithAttr(&sb, line, - config.Client.TermColors.ClientWarnFg, - config.Client.TermColors.ClientWarnBg, - config.Client.TermColors.ClientWarnAttr) - + case strings.HasPrefix(line, "CLIENT"): + paintClient(&sb, line) + + case strings.HasPrefix(line, "SERVER"): + paintServer(&sb, line) + + /* + case strings.Contains(line, "ERROR"): + color.PaintWithAttr(&sb, line, + config.Client.TermColors.ClientErrorFg, + config.Client.TermColors.ClientErrorBg, + config.Client.TermColors.ClientErrorAttr) + + case strings.Contains(line, "WARN"): + color.PaintWithAttr(&sb, line, + config.Client.TermColors.ClientWarnFg, + config.Client.TermColors.ClientWarnBg, + config.Client.TermColors.ClientWarnAttr) + */ default: color.PaintWithAttr(&sb, line, color.FgDefault, diff --git a/internal/config/client.go b/internal/config/client.go index 05e4f93..837c7d6 100644 --- a/internal/config/client.go +++ b/internal/config/client.go @@ -2,53 +2,80 @@ package config import "github.com/mimecast/dtail/internal/color" -// ClientColorConfig allows to override the default terminal color color. +type remoteTermColors struct { + DelimiterAttr color.Attribute + DelimiterBg color.BgColor + DelimiterFg color.FgColor + RemoteAttr color.Attribute + RemoteBg color.BgColor + RemoteFg color.FgColor + CountAttr color.Attribute + CountBg color.BgColor + CountFg color.FgColor + HostnameAttr color.Attribute + HostnameBg color.BgColor + HostnameFg color.FgColor + IdAttr color.Attribute + IdBg color.BgColor + IdFg color.FgColor + StatsOkAttr color.Attribute + StatsOkBg color.BgColor + StatsOkFg color.FgColor + StatsWarnAttr color.Attribute + StatsWarnBg color.BgColor + StatsWarnFg color.FgColor + TextAttr color.Attribute + TextBg color.BgColor + TextFg color.FgColor +} + +type clientTermColors struct { + DelimiterAttr color.Attribute + DelimiterBg color.BgColor + DelimiterFg color.FgColor + ClientAttr color.Attribute + ClientBg color.BgColor + ClientFg color.FgColor + HostnameAttr color.Attribute + HostnameBg color.BgColor + HostnameFg color.FgColor + TextAttr color.Attribute + TextBg color.BgColor + TextFg color.FgColor +} + +type serverTermColors struct { + DelimiterAttr color.Attribute + DelimiterBg color.BgColor + DelimiterFg color.FgColor + ServerAttr color.Attribute + ServerBg color.BgColor + ServerFg color.FgColor + HostnameAttr color.Attribute + HostnameBg color.BgColor + HostnameFg color.FgColor + TextAttr color.Attribute + TextBg color.BgColor + TextFg color.FgColor +} + +type commonTermColors struct { + SeverityErrorAttr color.Attribute + SeverityErrorBg color.BgColor + SeverityErrorFg color.FgColor + SeverityFatalAttr color.Attribute + SeverityFatalBg color.BgColor + SeverityFatalFg color.FgColor + SeverityWarnAttr color.Attribute + SeverityWarnBg color.BgColor + SeverityWarnFg color.FgColor +} + type termColors struct { - ClientErrorAttr color.Attribute - ClientErrorBg color.BgColor - ClientErrorFg color.FgColor - ClientWarnAttr color.Attribute - ClientWarnBg color.BgColor - ClientWarnFg color.FgColor - DelimiterAttr color.Attribute - DelimiterBg color.BgColor - DelimiterFg color.FgColor - RemoteCountAttr color.Attribute - RemoteCountBg color.BgColor - RemoteCountFg color.FgColor - RemoteDebugAttr color.Attribute - RemoteDebugBg color.BgColor - RemoteDebugFg color.FgColor - RemoteErrorAttr color.Attribute - RemoteErrorBg color.BgColor - RemoteErrorFg color.FgColor - RemoteFatalAttr color.Attribute - RemoteFatalBg color.BgColor - RemoteFatalFg color.FgColor - RemoteIdAttr color.Attribute - RemoteIdBg color.BgColor - RemoteIdFg color.FgColor - RemoteServerAttr color.Attribute - RemoteServerBg color.BgColor - RemoteServerFg color.FgColor - RemoteStatsOkAttr color.Attribute - RemoteStatsOkBg color.BgColor - RemoteStatsOkFg color.FgColor - RemoteStatsWarnAttr color.Attribute - RemoteStatsWarnBg color.BgColor - RemoteStatsWarnFg color.FgColor - RemoteStrAttr color.Attribute - RemoteStrBg color.BgColor - RemoteStrFg color.FgColor - RemoteTextAttr color.Attribute - RemoteTextBg color.BgColor - RemoteTextFg color.FgColor - RemoteTraceAttr color.Attribute - RemoteTraceBg color.BgColor - RemoteTraceFg color.FgColor - RemoteWarnAttr color.Attribute - RemoteWarnBg color.BgColor - RemoteWarnFg color.FgColor + Remote remoteTermColors + Client clientTermColors + Server serverTermColors + Common commonTermColors } // ClientConfig represents a DTail client configuration (empty as of now as there @@ -63,51 +90,71 @@ func newDefaultClientConfig() *ClientConfig { return &ClientConfig{ TermColorsEnable: true, TermColors: termColors{ - ClientErrorAttr: color.AttrBold, - ClientErrorBg: color.BgBlack, - ClientErrorFg: color.FgRed, - ClientWarnAttr: color.AttrNone, - ClientWarnBg: color.BgBlack, - ClientWarnFg: color.FgMagenta, - DelimiterAttr: color.AttrDim, - DelimiterBg: color.BgBlue, - DelimiterFg: color.FgCyan, - RemoteCountAttr: color.AttrDim, - RemoteCountBg: color.BgBlue, - RemoteCountFg: color.FgGreen, - RemoteDebugAttr: color.AttrBold, - RemoteDebugBg: color.BgBlack, - RemoteDebugFg: color.FgGreen, - RemoteErrorAttr: color.AttrBold, - RemoteErrorBg: color.BgRed, - RemoteErrorFg: color.FgWhite, - RemoteFatalAttr: color.AttrBlink, - RemoteFatalBg: color.BgRed, - RemoteFatalFg: color.FgWhite, - RemoteIdAttr: color.AttrDim, - RemoteIdBg: color.BgBlue, - RemoteIdFg: color.FgWhite, - RemoteServerAttr: color.AttrBold, - RemoteServerBg: color.BgBlue, - RemoteServerFg: color.FgWhite, - RemoteStatsOkAttr: color.AttrNone, - RemoteStatsOkBg: color.BgGreen, - RemoteStatsOkFg: color.FgBlue, - RemoteStatsWarnAttr: color.AttrNone, - RemoteStatsWarnBg: color.BgRed, - RemoteStatsWarnFg: color.FgWhite, - RemoteStrAttr: color.AttrDim, - RemoteStrBg: color.BgBlue, - RemoteStrFg: color.FgWhite, - RemoteTextAttr: color.AttrNone, - RemoteTextBg: color.BgBlack, - RemoteTextFg: color.FgWhite, - RemoteTraceAttr: color.AttrBold, - RemoteTraceBg: color.BgGreen, - RemoteTraceFg: color.FgWhite, - RemoteWarnAttr: color.AttrBold, - RemoteWarnBg: color.BgYellow, - RemoteWarnFg: color.FgWhite, + Remote: remoteTermColors{ + DelimiterAttr: color.AttrDim, + DelimiterBg: color.BgBlue, + DelimiterFg: color.FgCyan, + RemoteAttr: color.AttrDim, + RemoteBg: color.BgBlue, + RemoteFg: color.FgWhite, + CountAttr: color.AttrDim, + CountBg: color.BgBlue, + CountFg: color.FgGreen, + HostnameAttr: color.AttrBold, + HostnameBg: color.BgBlue, + HostnameFg: color.FgWhite, + IdAttr: color.AttrDim, + IdBg: color.BgBlue, + IdFg: color.FgWhite, + StatsOkAttr: color.AttrNone, + StatsOkBg: color.BgGreen, + StatsOkFg: color.FgBlue, + StatsWarnAttr: color.AttrNone, + StatsWarnBg: color.BgRed, + StatsWarnFg: color.FgWhite, + TextAttr: color.AttrNone, + TextBg: color.BgBlack, + TextFg: color.FgWhite, + }, + Client: clientTermColors{ + DelimiterAttr: color.AttrDim, + DelimiterBg: color.BgYellow, + DelimiterFg: color.FgBlack, + ClientAttr: color.AttrDim, + ClientBg: color.BgYellow, + ClientFg: color.FgBlack, + HostnameAttr: color.AttrDim, + HostnameBg: color.BgYellow, + HostnameFg: color.FgBlack, + TextAttr: color.AttrNone, + TextBg: color.BgYellow, + TextFg: color.FgBlack, + }, + Server: serverTermColors{ + DelimiterAttr: color.AttrDim, + DelimiterBg: color.BgCyan, + DelimiterFg: color.FgBlack, + ServerAttr: color.AttrDim, + ServerBg: color.BgCyan, + ServerFg: color.FgBlack, + HostnameAttr: color.AttrBold, + HostnameBg: color.BgCyan, + HostnameFg: color.FgBlack, + TextAttr: color.AttrNone, + TextBg: color.BgCyan, + TextFg: color.FgBlack, + }, + Common: commonTermColors{ + SeverityErrorAttr: color.AttrBold, + SeverityErrorBg: color.BgRed, + SeverityErrorFg: color.FgWhite, + SeverityFatalAttr: color.AttrBlink, + SeverityFatalBg: color.BgRed, + SeverityFatalFg: color.FgWhite, + SeverityWarnAttr: color.AttrNone, + SeverityWarnBg: color.BgBlack, + SeverityWarnFg: color.FgRed, + }, }, } } |
