enable coloring by UIDs

This commit is contained in:
Dominic Breuker
2019-04-24 22:30:14 +02:00
parent d1b6518db5
commit 21a0666ff1
4 changed files with 67 additions and 41 deletions

View File

@@ -2,14 +2,20 @@ package logging
import ( import (
"fmt" "fmt"
"hash/fnv"
"log" "log"
"os" "os"
"strconv"
) )
const ( const (
ColorNone = iota ColorNone = iota
ColorRed ColorRed
ColorGreen ColorGreen
ColorYellow
ColorBlue
ColorPurple
ColorTeal
) )
type Logger struct { type Logger struct {
@@ -43,14 +49,15 @@ func (l *Logger) Errorf(debug bool, format string, v ...interface{}) {
// Eventf writes an event with timestamp to stdout // Eventf writes an event with timestamp to stdout
func (l *Logger) Eventf(color int, format string, v ...interface{}) { func (l *Logger) Eventf(color int, format string, v ...interface{}) {
msg := fmt.Sprintf(format, v...) msg := fmt.Sprintf(format, v...)
if color != ColorNone {
switch color { msg = fmt.Sprintf("\x1b[%d;1m%s\x1b[0m", 30+color, msg)
case ColorRed:
msg = fmt.Sprintf("\x1b[31;1m%s\x1b[0m", msg)
case ColorGreen:
msg = fmt.Sprintf("\x1b[32;1m%s\x1b[0m", msg)
default:
} }
l.eventLogger.Printf("%s", msg) l.eventLogger.Printf("%s", msg)
} }
func GetColorByUID(uid int) int {
h := fnv.New32a()
h.Write([]byte(strconv.Itoa(uid)))
return (int(h.Sum32()) % (ColorTeal)) + 1
}

View File

@@ -33,6 +33,7 @@ var logTests = []struct {
func TestLogging(t *testing.T) { func TestLogging(t *testing.T) {
for i, tt := range logTests { for i, tt := range logTests {
actual := captureOutput(tt.logger, tt.test) actual := captureOutput(tt.logger, tt.test)
log.Printf("OUT: %s", actual)
// check colors and remove afterwards // check colors and remove afterwards
colors := ansiMatcher.FindAll(actual, 2) colors := ansiMatcher.FindAll(actual, 2)
@@ -55,3 +56,46 @@ func captureOutput(logger *log.Logger, f func()) []byte {
f() f()
return buf.Bytes() return buf.Bytes()
} }
func TestGetColorByUID(t *testing.T) {
tests := []struct {
uid int
color int
}{
{uid: 0, color: 4},
{uid: 1, color: 5},
{uid: 2, color: 2},
{uid: 3, color: 3},
{uid: 99999999999, color: 5},
}
for _, tt := range tests {
color := GetColorByUID(tt.uid)
if color != tt.color {
t.Errorf("GetColorByUID(%d)=%d but want %d", tt.uid, color, tt.color)
}
}
minColor := 9999999
maxColor := -9999999
for i := 0; i < 1000; i++ {
color := GetColorByUID(i)
if color < 1 || color > ColorTeal {
t.Fatalf("GetColorByUID(%d)=%d but this is out of range [%d, %d]", i, color, ColorRed, ColorTeal)
}
if color < minColor {
minColor = color
}
if color > maxColor {
maxColor = color
}
}
if minColor != 1 {
t.Errorf("GetColorByUID returned minimum color %d, not %d, on 1000 trials, which is extremely unlikely", minColor, 1)
}
if maxColor != ColorTeal {
t.Errorf("GetColorByUID returned maximum color %d, not %d, on 1000 trials, which is extremely unlikely", maxColor, ColorTeal)
}
}

View File

@@ -57,7 +57,7 @@ func Start(cfg *config.Config, b *Bindings, sigCh chan os.Signal) chan struct{}
func printOutput(cfg *config.Config, b *Bindings, chans *chans) chan struct{} { func printOutput(cfg *config.Config, b *Bindings, chans *chans) chan struct{} {
exit := make(chan struct{}) exit := make(chan struct{})
fsEventColor, psEventColor := getColors(cfg.Colored) // fsEventColor, psEventColor := getColors(cfg.Colored)
go func() { go func() {
for { for {
@@ -67,11 +67,15 @@ func printOutput(cfg *config.Config, b *Bindings, chans *chans) chan struct{} {
exit <- struct{}{} exit <- struct{}{}
case fe := <-chans.fsEventCh: case fe := <-chans.fsEventCh:
if cfg.LogFS { if cfg.LogFS {
b.Logger.Eventf(fsEventColor, "FS: %+v", fe) b.Logger.Eventf(logging.ColorNone, "FS: %+v", fe)
} }
case pe := <-chans.psEventCh: case pe := <-chans.psEventCh:
if cfg.LogPS { if cfg.LogPS {
b.Logger.Eventf(psEventColor, "CMD: %+v", pe) color := logging.ColorNone
if cfg.Colored {
color = logging.GetColorByUID(pe.UID)
}
b.Logger.Eventf(color, "CMD: %+v", pe)
} }
} }
} }
@@ -79,17 +83,6 @@ func printOutput(cfg *config.Config, b *Bindings, chans *chans) chan struct{} {
return exit return exit
} }
func getColors(colored bool) (fsEventColor int, psEventColor int) {
if colored {
fsEventColor = logging.ColorGreen
psEventColor = logging.ColorRed
} else {
fsEventColor = logging.ColorNone
psEventColor = logging.ColorNone
}
return
}
func initFSW(fsw FSWatcher, rdirs, dirs []string, logger Logger) { func initFSW(fsw FSWatcher, rdirs, dirs []string, logger Logger) {
errCh, doneCh := fsw.Init(rdirs, dirs) errCh, doneCh := fsw.Init(rdirs, dirs)
for { for {

View File

@@ -68,24 +68,6 @@ func TestStartPSS(t *testing.T) {
expectMessage(t, l.Error, "ERROR: error during refresh") expectMessage(t, l.Error, "ERROR: error during refresh")
} }
func TestGetColors(t *testing.T) {
tests := []struct {
colored bool
fsEventColor int
psEventColor int
}{
{colored: true, fsEventColor: logging.ColorGreen, psEventColor: logging.ColorRed},
{colored: false, fsEventColor: logging.ColorNone, psEventColor: logging.ColorNone},
}
for _, tt := range tests {
c1, c2 := getColors(tt.colored)
if c1 != tt.fsEventColor || c2 != tt.psEventColor {
t.Errorf("Got wrong colors when colored=%t: expected %d, %d but got %d, %d", tt.colored, tt.fsEventColor, tt.psEventColor, c1, c2)
}
}
}
func TestStart(t *testing.T) { func TestStart(t *testing.T) {
drainFor := 10 * time.Millisecond drainFor := 10 * time.Millisecond
triggerEvery := 999 * time.Second triggerEvery := 999 * time.Second
@@ -126,9 +108,9 @@ func TestStart(t *testing.T) {
<-time.After(2 * drainFor) <-time.After(2 * drainFor)
expectMessage(t, l.Info, "done") expectMessage(t, l.Info, "done")
expectTrigger(t, pss.runTriggerCh) // pss receives triggers from fsw expectTrigger(t, pss.runTriggerCh) // pss receives triggers from fsw
expectMessage(t, l.Event, fmt.Sprintf("%d CMD: UID=1000 PID=12345 | pss event", logging.ColorRed)) expectMessage(t, l.Event, fmt.Sprintf("%d CMD: UID=1000 PID=12345 | pss event", logging.ColorPurple))
expectMessage(t, l.Error, "ERROR: pss error") expectMessage(t, l.Error, "ERROR: pss error")
expectMessage(t, l.Event, fmt.Sprintf("%d FS: fsw event", logging.ColorGreen)) expectMessage(t, l.Event, fmt.Sprintf("%d FS: fsw event", logging.ColorNone))
expectMessage(t, l.Error, "ERROR: fsw error") expectMessage(t, l.Error, "ERROR: fsw error")
expectMessage(t, l.Info, "Exiting program... (interrupt)") expectMessage(t, l.Info, "Exiting program... (interrupt)")