safing-portbase/log/output.go

120 lines
2.5 KiB
Go

package log
import (
"fmt"
"time"
)
var (
schedulingEnabled = false
writeTrigger = make(chan struct{})
)
// EnableScheduling enables external scheduling of the logger. This will require to manually trigger writes via TriggerWrite whenevery logs should be written. Please note that full buffers will also trigger writing. Must be called before Start() to have an effect.
func EnableScheduling() {
if !initializing.IsSet() {
schedulingEnabled = true
}
}
// TriggerWriter triggers log output writing.
func TriggerWriter() {
if started.IsSet() && schedulingEnabled {
select {
case writeTrigger <- struct{}{}:
}
}
}
func writeLine(line *logLine, duplicates uint64) {
fmt.Println(formatLine(line, duplicates, true))
// TODO: implement file logging and setting console/file logging
// TODO: use https://github.com/natefinch/lumberjack
}
func startWriter() {
shutdownWaitGroup.Add(1)
fmt.Println(fmt.Sprintf("%s%s %s BOF%s", InfoLevel.color(), time.Now().Format("060102 15:04:05.000"), rightArrow, endColor()))
go writer()
}
func writer() {
var line *logLine
var lastLine *logLine
var duplicates uint64
defer shutdownWaitGroup.Done()
for {
// reset
line = nil
lastLine = nil
duplicates = 0
// wait until logs need to be processed
select {
case <-logsWaiting:
logsWaitingFlag.UnSet()
case <-shutdownSignal:
}
// wait for timeslot to log, or when buffer is full
select {
case <-writeTrigger:
case <-forceEmptyingOfBuffer:
case <-shutdownSignal:
for {
select {
case line = <-logBuffer:
writeLine(line, duplicates)
case <-time.After(10 * time.Millisecond):
fmt.Println(fmt.Sprintf("%s%s %s EOF%s", InfoLevel.color(), time.Now().Format("060102 15:04:05.000"), leftArrow, endColor()))
return
}
}
}
// write all the logs!
writeLoop:
for {
select {
case line = <-logBuffer:
// look-ahead for deduplication (best effort)
dedupLoop:
for {
// check if there is another line waiting
select {
case nextLine := <-logBuffer:
lastLine = line
line = nextLine
default:
break dedupLoop
}
// deduplication
if !line.Equal(lastLine) {
// no duplicate
writeLine(lastLine, duplicates)
duplicates = 0
} else {
// duplicate
duplicates++
}
}
// write actual line
writeLine(line, duplicates)
duplicates = 0
default:
break writeLoop
}
}
// back down a little
select {
case <-time.After(10 * time.Millisecond):
case <-shutdownSignal:
}
}
}