sys.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package logger
  2. import (
  3. "sync"
  4. )
  5. type message struct {
  6. level LogLevel
  7. msg string
  8. }
  9. var (
  10. logMessageC = make(chan message)
  11. addSystemC = make(chan LogSystem)
  12. flushC = make(chan chan struct{})
  13. resetC = make(chan chan struct{})
  14. )
  15. func init() {
  16. go dispatchLoop()
  17. }
  18. // each system can buffer this many messages before
  19. // blocking incoming log messages.
  20. const sysBufferSize = 500
  21. func dispatchLoop() {
  22. var (
  23. systems []LogSystem
  24. systemIn []chan message
  25. systemWG sync.WaitGroup
  26. )
  27. bootSystem := func(sys LogSystem) {
  28. in := make(chan message, sysBufferSize)
  29. systemIn = append(systemIn, in)
  30. systemWG.Add(1)
  31. go sysLoop(sys, in, &systemWG)
  32. }
  33. for {
  34. select {
  35. case msg := <-logMessageC:
  36. for _, c := range systemIn {
  37. c <- msg
  38. }
  39. case sys := <-addSystemC:
  40. systems = append(systems, sys)
  41. bootSystem(sys)
  42. case waiter := <-resetC:
  43. // reset means terminate all systems
  44. for _, c := range systemIn {
  45. close(c)
  46. }
  47. systems = nil
  48. systemIn = nil
  49. systemWG.Wait()
  50. close(waiter)
  51. case waiter := <-flushC:
  52. // flush means reboot all systems
  53. for _, c := range systemIn {
  54. close(c)
  55. }
  56. systemIn = nil
  57. systemWG.Wait()
  58. for _, sys := range systems {
  59. bootSystem(sys)
  60. }
  61. close(waiter)
  62. }
  63. }
  64. }
  65. func sysLoop(sys LogSystem, in <-chan message, wg *sync.WaitGroup) {
  66. for msg := range in {
  67. switch sys.(type) {
  68. case *jsonLogSystem:
  69. if msg.level == JsonLevel {
  70. sys.LogPrint(msg.level, msg.msg)
  71. }
  72. default:
  73. if sys.GetLogLevel() >= msg.level {
  74. sys.LogPrint(msg.level, msg.msg)
  75. }
  76. }
  77. }
  78. wg.Done()
  79. }
  80. // Reset removes all active log systems.
  81. // It blocks until all current messages have been delivered.
  82. func Reset() {
  83. waiter := make(chan struct{})
  84. resetC <- waiter
  85. <-waiter
  86. }
  87. // Flush waits until all current log messages have been dispatched to
  88. // the active log systems.
  89. func Flush() {
  90. waiter := make(chan struct{})
  91. flushC <- waiter
  92. <-waiter
  93. }
  94. // AddLogSystem starts printing messages to the given LogSystem.
  95. func AddLogSystem(sys LogSystem) {
  96. addSystemC <- sys
  97. }