package log import ( "context" "errors" "fmt" "log" "os" "sync" "time" ) var globalBuffer struct { sync.Mutex entries []Entry handlers []func(Entry) } func init() { AddEntryHandler(func(entry Entry) { fmt.Fprintln(os.Stderr, entry) }) } type Entry struct { Time time.Time Msg string } func (entry Entry) String() string { return entry.Time.Format(time.Stamp) + ": " + entry.Msg } // AddEntryHandler adds a handler, which will run asynchronously. func AddEntryHandler(fn func(Entry)) { globalBuffer.handlers = append(globalBuffer.handlers, fn) } func Error(err error) { // Ignore nil errors. if err == nil { return } // Ignore context cancel errors. if errors.Is(err, context.Canceled) { return } Write("Error: " + err.Error()) } // Warn calls Info(). func Warn(err error) { Info(err) } func Info(err error) { Write("Info: " + err.Error()) } func Write(msg string) { WriteEntry(Entry{ Time: time.Now(), Msg: msg, }) } func WriteEntry(entry Entry) { go func() { globalBuffer.Lock() globalBuffer.entries = append(globalBuffer.entries, entry) globalBuffer.Unlock() for _, fn := range globalBuffer.handlers { fn(entry) } }() } func Println(v ...interface{}) { log.Println(v...) } func Printlnf(f string, v ...interface{}) { log.Printf(f+"\n", v...) }