| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- package logger
- import (
- "fmt"
- "sync"
- )
- type stdMsg struct {
- level LogLevel
- msg string
- }
- type jsonMsg []byte
- func (m jsonMsg) Level() LogLevel {
- return 0
- }
- func (m jsonMsg) String() string {
- return string(m)
- }
- type LogMsg interface {
- Level() LogLevel
- fmt.Stringer
- }
- func (m stdMsg) Level() LogLevel {
- return m.level
- }
- func (m stdMsg) String() string {
- return m.msg
- }
- var (
- logMessageC = make(chan LogMsg)
- addSystemC = make(chan LogSystem)
- flushC = make(chan chan struct{})
- resetC = make(chan chan struct{})
- )
- func init() {
- go dispatchLoop()
- }
- // each system can buffer this many messages before
- // blocking incoming log messages.
- const sysBufferSize = 500
- func dispatchLoop() {
- var (
- systems []LogSystem
- systemIn []chan LogMsg
- systemWG sync.WaitGroup
- )
- bootSystem := func(sys LogSystem) {
- in := make(chan LogMsg, sysBufferSize)
- systemIn = append(systemIn, in)
- systemWG.Add(1)
- go sysLoop(sys, in, &systemWG)
- }
- for {
- select {
- case msg := <-logMessageC:
- for _, c := range systemIn {
- c <- msg
- }
- case sys := <-addSystemC:
- systems = append(systems, sys)
- bootSystem(sys)
- case waiter := <-resetC:
- // reset means terminate all systems
- for _, c := range systemIn {
- close(c)
- }
- systems = nil
- systemIn = nil
- systemWG.Wait()
- close(waiter)
- case waiter := <-flushC:
- // flush means reboot all systems
- for _, c := range systemIn {
- close(c)
- }
- systemIn = nil
- systemWG.Wait()
- for _, sys := range systems {
- bootSystem(sys)
- }
- close(waiter)
- }
- }
- }
- func sysLoop(sys LogSystem, in <-chan LogMsg, wg *sync.WaitGroup) {
- for msg := range in {
- sys.LogPrint(msg)
- }
- wg.Done()
- }
- // Reset removes all active log systems.
- // It blocks until all current messages have been delivered.
- func Reset() {
- waiter := make(chan struct{})
- resetC <- waiter
- <-waiter
- }
- // Flush waits until all current log messages have been dispatched to
- // the active log systems.
- func Flush() {
- waiter := make(chan struct{})
- flushC <- waiter
- <-waiter
- }
- // AddLogSystem starts printing messages to the given LogSystem.
- func AddLogSystem(sys LogSystem) {
- addSystemC <- sys
- }
|