sys.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // Copyright 2015 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package logger
  17. import (
  18. "fmt"
  19. "sync"
  20. )
  21. type stdMsg struct {
  22. level LogLevel
  23. msg string
  24. }
  25. type jsonMsg []byte
  26. func (m jsonMsg) Level() LogLevel {
  27. return 0
  28. }
  29. func (m jsonMsg) String() string {
  30. return string(m)
  31. }
  32. type LogMsg interface {
  33. Level() LogLevel
  34. fmt.Stringer
  35. }
  36. func (m stdMsg) Level() LogLevel {
  37. return m.level
  38. }
  39. func (m stdMsg) String() string {
  40. return m.msg
  41. }
  42. var (
  43. logMessageC = make(chan LogMsg)
  44. addSystemC = make(chan LogSystem)
  45. flushC = make(chan chan struct{})
  46. resetC = make(chan chan struct{})
  47. )
  48. func init() {
  49. go dispatchLoop()
  50. }
  51. // each system can buffer this many messages before
  52. // blocking incoming log messages.
  53. const sysBufferSize = 500
  54. func dispatchLoop() {
  55. var (
  56. systems []LogSystem
  57. systemIn []chan LogMsg
  58. systemWG sync.WaitGroup
  59. )
  60. bootSystem := func(sys LogSystem) {
  61. in := make(chan LogMsg, sysBufferSize)
  62. systemIn = append(systemIn, in)
  63. systemWG.Add(1)
  64. go sysLoop(sys, in, &systemWG)
  65. }
  66. for {
  67. select {
  68. case msg := <-logMessageC:
  69. for _, c := range systemIn {
  70. c <- msg
  71. }
  72. case sys := <-addSystemC:
  73. systems = append(systems, sys)
  74. bootSystem(sys)
  75. case waiter := <-resetC:
  76. // reset means terminate all systems
  77. for _, c := range systemIn {
  78. close(c)
  79. }
  80. systems = nil
  81. systemIn = nil
  82. systemWG.Wait()
  83. close(waiter)
  84. case waiter := <-flushC:
  85. // flush means reboot all systems
  86. for _, c := range systemIn {
  87. close(c)
  88. }
  89. systemIn = nil
  90. systemWG.Wait()
  91. for _, sys := range systems {
  92. bootSystem(sys)
  93. }
  94. close(waiter)
  95. }
  96. }
  97. }
  98. func sysLoop(sys LogSystem, in <-chan LogMsg, wg *sync.WaitGroup) {
  99. for msg := range in {
  100. sys.LogPrint(msg)
  101. }
  102. wg.Done()
  103. }
  104. // Reset removes all active log systems.
  105. // It blocks until all current messages have been delivered.
  106. func Reset() {
  107. waiter := make(chan struct{})
  108. resetC <- waiter
  109. <-waiter
  110. }
  111. // Flush waits until all current log messages have been dispatched to
  112. // the active log systems.
  113. func Flush() {
  114. waiter := make(chan struct{})
  115. flushC <- waiter
  116. <-waiter
  117. }
  118. // AddLogSystem starts printing messages to the given LogSystem.
  119. func AddLogSystem(sys LogSystem) {
  120. addSystemC <- sys
  121. }