imposm3/logging/logger.go

252 lines
5.2 KiB
Go

package logging
import (
"fmt"
"os"
"sync"
"time"
)
type Level int
const (
FATAL Level = iota
ERROR
WARNING
INFO
DEBUG
)
type Record struct {
Level Level
Component string
Message string
}
const (
CLEARLINE = "\x1b[2K"
)
func Debugf(msg string, args ...interface{}) {
defaultLogBroker.Records <- Record{DEBUG, "", fmt.Sprintf(msg, args...)}
}
func Infof(msg string, args ...interface{}) {
defaultLogBroker.Records <- Record{INFO, "", fmt.Sprintf(msg, args...)}
}
func Warnf(msg string, args ...interface{}) {
defaultLogBroker.Records <- Record{WARNING, "", fmt.Sprintf(msg, args...)}
}
func Errorf(msg string, args ...interface{}) {
defaultLogBroker.Records <- Record{ERROR, "", fmt.Sprintf(msg, args...)}
}
func Fatalf(msg string, args ...interface{}) {
defaultLogBroker.Records <- Record{FATAL, "", fmt.Sprintf(msg, args...)}
Shutdown()
os.Exit(1)
}
func Progress(msg string) {
defaultLogBroker.Progress <- msg
}
func SetQuiet(quiet bool) {
defaultLogBroker.SetQuiet(quiet)
}
type Logger struct {
Component string
}
func (l *Logger) Print(args ...interface{}) {
defaultLogBroker.Records <- Record{INFO, l.Component, fmt.Sprint(args...)}
}
func (l *Logger) Printf(msg string, args ...interface{}) {
defaultLogBroker.Records <- Record{INFO, l.Component, fmt.Sprintf(msg, args...)}
}
func (l *Logger) Fatal(args ...interface{}) {
defaultLogBroker.Records <- Record{FATAL, l.Component, fmt.Sprint(args...)}
Shutdown()
os.Exit(1)
}
func (l *Logger) Fatalf(msg string, args ...interface{}) {
defaultLogBroker.Records <- Record{FATAL, l.Component, fmt.Sprintf(msg, args...)}
Shutdown()
os.Exit(1)
}
func (l *Logger) Error(args ...interface{}) {
defaultLogBroker.Records <- Record{ERROR, l.Component, fmt.Sprint(args...)}
}
func (l *Logger) Errorf(msg string, args ...interface{}) {
defaultLogBroker.Records <- Record{ERROR, l.Component, fmt.Sprintf(msg, args...)}
}
func (l *Logger) Warn(args ...interface{}) {
defaultLogBroker.Records <- Record{WARNING, l.Component, fmt.Sprint(args...)}
}
func (l *Logger) Warnf(msg string, args ...interface{}) {
defaultLogBroker.Records <- Record{WARNING, l.Component, fmt.Sprintf(msg, args...)}
}
func (l *Logger) Printfl(level Level, msg string, args ...interface{}) {
defaultLogBroker.Records <- Record{level, l.Component, fmt.Sprintf(msg, args...)}
}
func (l *Logger) StartStep(msg string) string {
defaultLogBroker.StepStart <- Step{l.Component, msg}
return msg
}
func (l *Logger) StopStep(msg string) {
defaultLogBroker.StepStop <- Step{l.Component, msg}
}
func NewLogger(component string) *Logger {
return &Logger{component}
}
type Step struct {
Component string
Name string
}
type LogBroker struct {
Records chan Record
Progress chan string
StepStart chan Step
StepStop chan Step
quiet bool
quit chan bool
wg *sync.WaitGroup
newline bool
lastProgress string
}
func (l *LogBroker) SetQuiet(quiet bool) {
l.quiet = quiet
}
func (l *LogBroker) loop() {
l.wg.Add(1)
steps := make(map[Step]time.Time)
For:
for {
select {
case record := <-l.Records:
l.printRecord(record)
case progress := <-l.Progress:
if !l.quiet {
l.printProgress(progress)
}
case step := <-l.StepStart:
steps[step] = time.Now()
l.printProgress(step.Name)
case step := <-l.StepStop:
startTime := steps[step]
delete(steps, step)
duration := time.Since(startTime)
l.lastProgress = ""
l.printRecord(Record{INFO, step.Component, step.Name + " took: " + duration.String()})
case <-l.quit:
break For
}
}
Flush:
// after quit, print all records from chan
for {
select {
case record := <-l.Records:
l.printRecord(record)
default:
break Flush
}
}
l.wg.Done()
}
func (l *LogBroker) printPrefix() {
fmt.Print("[", time.Now().Format(time.Stamp), "] ")
}
func (l *LogBroker) printComponent(component string) {
if component != "" {
fmt.Print("[", component, "] ")
}
}
func (l *LogBroker) printLevel(level Level) {
switch level {
case INFO:
fmt.Print("[INFO] ")
case WARNING:
fmt.Print("[WARN] ")
case ERROR:
fmt.Print("[ERR] ")
}
}
func (l *LogBroker) printRecord(record Record) {
if !l.newline {
fmt.Print(CLEARLINE)
}
l.printPrefix()
l.printLevel(record.Level)
l.printComponent(record.Component)
fmt.Println(record.Message)
l.newline = true
if l.lastProgress != "" {
l.printProgress(l.lastProgress)
l.newline = false
}
}
func (l *LogBroker) printProgress(progress string) {
l.printPrefix()
fmt.Print(progress)
if l.quiet {
fmt.Print("\n")
l.lastProgress = ""
l.newline = true
} else {
fmt.Print("\r")
l.lastProgress = progress
l.newline = false
}
}
func Shutdown() {
defaultLogBroker.quit <- true
defaultLogBroker.wg.Wait()
}
var defaultLogBroker LogBroker
func init() {
defaultLogBroker = LogBroker{
Records: make(chan Record, 8),
Progress: make(chan string),
StepStart: make(chan Step),
StepStop: make(chan Step),
quit: make(chan bool),
wg: &sync.WaitGroup{},
}
go defaultLogBroker.loop()
}
// func init() {
// go func() {
// log := NewLogger("Tourette")
// for {
// time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
// log.Printfl(Level(rand.Intn(5)), "Bazinga")
// }
// }()
// }